{"id":49364,"date":"2026-09-05T21:59:47","date_gmt":"2026-09-06T01:59:47","guid":{"rendered":"https:\/\/www.thebeertimes.com\/?page_id=49364"},"modified":"2026-09-07T19:15:42","modified_gmt":"2026-09-07T23:15:42","slug":"beer-sommelier-digital","status":"publish","type":"page","link":"https:\/\/www.thebeertimes.com\/en\/beer-sommelier-digital\/","title":{"rendered":"Beer Sommelier Digital"},"content":{"rendered":"<!-- El Sommelier \u2014 The Beer Times. Self-contained block, paste as-is in a \"Custom HTML\" block (Gutenberg) or in an HFCM snippet. No external dependencies, no network calls. -->\r\n<p>Beer Sommelier is The Beer Times\u2122&#8217;s pairing tool. It recommends combinations between food and beer based on currently recognized beer styles and the three classic pairing principles: affinity, contrast, and complement.<\/p>\r\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-49319 size-full aligncenter\" title=\"Beer Sommelier\" src=\"https:\/\/www.thebeertimes.com\/wp-content\/uploads\/2026\/09\/Beer-Sommelier.jpg\" alt=\"Beer Sommelier\" width=\"600\" height=\"315\" srcset=\"https:\/\/www.thebeertimes.com\/wp-content\/uploads\/2026\/09\/Beer-Sommelier.jpg 600w, https:\/\/www.thebeertimes.com\/wp-content\/uploads\/2026\/09\/Beer-Sommelier-300x158.jpg 300w\" sizes=\"auto, (max-width: 600px) 100vw, 600px\" \/><\/p>\r\n<p>Choose whether you want to start from a dish or a beer, select an option from the list (or type to filter it), and the system displays the best-matching combinations, with the technical reasoning behind each choice.<\/p>\r\n<h2>What Is a Beer Sommelier?<\/h2>\r\n<p>Simply put, a beer sommelier is a beer specialist who knows its styles, aromas, flavors, and characteristics in order to recommend suitable pairings with different foods.<\/p>\r\n<div id=\"tbt-sommelier\" class=\"tbt-sommelier\">\r\n<div class=\"tbt-som-tabs\" role=\"tablist\"><button class=\"tbt-som-tab is-active\" role=\"tab\" type=\"button\" data-mode=\"comida\" aria-selected=\"true\">I Have a Dish<\/button> <button class=\"tbt-som-tab\" role=\"tab\" type=\"button\" data-mode=\"cerveza\" aria-selected=\"false\">I Have a Beer<\/button><\/div>\r\n<div class=\"tbt-som-search\"><input class=\"tbt-som-search-input\" type=\"text\" placeholder=\"Filter categories or styles\u2026\" aria-label=\"Filter options\" \/><\/div>\r\n<div class=\"tbt-som-chips\" role=\"group\" aria-label=\"Select an option\">\u00a0<\/div>\r\n<div class=\"tbt-som-results\" aria-live=\"polite\">\u00a0<\/div>\r\n<\/div>\r\n<p><style>\r\n\r\n\r\n\r\n  .tbt-sommelier{\r\n\r\n\r\n\r\n    --tbt-ink:#111111;\r\n\r\n\r\n\r\n    --tbt-body:#494949;\r\n\r\n\r\n\r\n    --tbt-muted:#898989;\r\n\r\n\r\n\r\n    --tbt-line:#dddddd;\r\n\r\n\r\n\r\n    max-width:720px;\r\n\r\n\r\n\r\n    margin:2rem auto;\r\n\r\n\r\n\r\n    font-family:Roboto,Arial,Helvetica,sans-serif;\r\n\r\n\r\n\r\n    color:var(--tbt-body);\r\n\r\n\r\n\r\n    line-height:1.45;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n  .tbt-sommelier *{box-sizing:border-box;}\r\n\r\n\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-intro{\r\n\r\n\r\n\r\n    font-size:1.13rem;line-height:1.6;color:var(--tbt-body);margin:0 0 1.2rem;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-tabs{\r\n\r\n\r\n\r\n    display:flex;gap:1.4rem;border-bottom:1px solid var(--tbt-line);margin-bottom:1rem;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-tab{\r\n\r\n\r\n\r\n    background:none;border:none;padding:.2rem 0 .7rem;cursor:pointer;\r\n\r\n\r\n\r\n    font-family:inherit;font-size:.95rem;color:var(--tbt-muted);\r\n\r\n\r\n\r\n    border-bottom:2px solid transparent;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-tab.is-active{color:var(--tbt-ink);font-weight:700;border-bottom-color:var(--tbt-ink);}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-tab:focus-visible{outline:2px solid var(--tbt-ink);outline-offset:2px;}\r\n\r\n\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-search{margin-bottom:.9rem;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-search-input{\r\n\r\n\r\n\r\n    width:100%;padding:.65rem .8rem;border:1px solid var(--tbt-ink);border-radius:3px;\r\n\r\n\r\n\r\n    font-family:inherit;font-size:1.09rem;color:var(--tbt-ink);background:#fff;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-search-input:focus-visible{outline:2px solid var(--tbt-ink);outline-offset:1px;}\r\n\r\n\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-chips{\r\n\r\n\r\n\r\n    display:flex;flex-wrap:wrap;gap:.5rem;margin-bottom:1.5rem;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-chip{\r\n\r\n\r\n\r\n    font-family:inherit;font-size:.91rem;letter-spacing:.03em;text-transform:uppercase;font-weight:600;\r\n\r\n\r\n\r\n    padding:.45rem .7rem;border-radius:3px;border:1px solid var(--tbt-ink);background:#fff;color:var(--tbt-ink);\r\n\r\n\r\n\r\n    text-align:left;\r\n\r\n\r\n\r\n    cursor:pointer;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-chip.is-selected{background:var(--tbt-ink);border-color:var(--tbt-ink);color:#fff;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-chip:focus-visible{outline:2px solid var(--tbt-ink);outline-offset:2px;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-chip.is-hidden{display:none;}\r\n\r\n\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-results{display:flex;flex-direction:column;gap:.9rem;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-results-heading{\r\n\r\n\r\n\r\n    font-size:1.14rem;font-weight:700;color:var(--tbt-ink);margin:0 0 .2rem;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-card{\r\n\r\n\r\n\r\n    border:1px solid var(--tbt-line);border-radius:5px;padding:.9rem 1rem;\r\n\r\n\r\n\r\n    display:flex;flex-direction:column;gap:.55rem;background:#fff;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-card-head{display:flex;align-items:flex-start;justify-content:space-between;gap:.6rem;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-card-head h3{margin:0;font-size:1.17rem;color:var(--tbt-ink);font-weight:700;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-badge{\r\n\r\n\r\n\r\n    font-size:.81rem;letter-spacing:.03em;text-transform:uppercase;font-weight:700;\r\n\r\n\r\n\r\n    padding:.22rem .45rem;border-radius:3px;white-space:nowrap;flex:none;\r\n\r\n\r\n\r\n    background:var(--tbt-ink);color:#fff;text-decoration:none;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-attrs{display:flex;gap:1.1rem;font-variant-numeric:tabular-nums;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-attrs div{display:flex;flex-direction:column;gap:.1rem;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-attrs .k{font-size:.79rem;color:var(--tbt-muted);text-transform:uppercase;letter-spacing:.06em;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-attrs .v{font-size:.99rem;color:var(--tbt-ink);font-weight:500;}\r\n\r\n\r\n\r\n  .tbt-sommelier{\r\n\r\n\r\n\r\n    --tbt-cat-afinidad:#d97706;\r\n\r\n\r\n\r\n    --tbt-cat-contraste:#3b82f6;\r\n\r\n\r\n\r\n    --tbt-cat-complemento:#7c2d92;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-tag{\r\n\r\n\r\n\r\n    display:inline-block;font-size:.72rem;letter-spacing:.05em;text-transform:uppercase;font-weight:700;\r\n\r\n\r\n\r\n    border:1px solid transparent;border-radius:3px;\r\n\r\n\r\n\r\n    padding:.12rem .4rem;margin-bottom:.35rem;text-align:left;width:auto;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-tag--afinidad{background:#fef3c7;color:#92400e;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-tag--contraste{background:#dbeafe;color:#1e40af;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-tag--complemento{background:#f3e8f7;color:#5b1f6e;}\r\n\r\n\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-card--afinidad{border-left:4px solid var(--tbt-cat-afinidad);}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-card--contraste{border-left:4px solid var(--tbt-cat-contraste);}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-card--complemento{border-left:4px solid var(--tbt-cat-complemento);}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-why{font-size:1.04rem;color:var(--tbt-body);margin:0;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-foot{\r\n\r\n\r\n\r\n    display:flex;align-items:center;justify-content:space-between;border-top:1px solid var(--tbt-line);\r\n\r\n\r\n\r\n    padding-top:.5rem;margin-top:.1rem;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-foot span{font-size:.91rem;color:var(--tbt-muted);}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-fb{display:flex;gap:.4rem;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-fb button{\r\n\r\n\r\n\r\n    font-family:inherit;font-size:.7rem;border:1px solid transparent;background:none;color:var(--tbt-ink);\r\n\r\n\r\n\r\n    padding:.2rem .55rem;border-radius:3px;cursor:pointer;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-fb button.tbt-som-fb-yes{background:#dcfce7;color:#166534;border-color:#bbf7d0;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-fb button.tbt-som-fb-no{background:#fee2e2;color:#991b1b;border-color:#fecaca;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-fb button.tbt-som-fb-yes.is-voted{background:#16a34a;color:#fff;border-color:#16a34a;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-fb button.tbt-som-fb-no.is-voted{background:#dc2626;color:#fff;border-color:#dc2626;}\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-fb button:disabled{opacity:.5;cursor:default;}\r\n\r\n\r\n\r\n\r\n\r\n  .tbt-sommelier .tbt-som-empty{font-size:1.04rem;color:var(--tbt-muted);}\r\n\r\n\r\n\r\n<\/style> <script>\r\n\r\n\r\n\r\n(function(){\r\n\r\n\r\n\r\n  \"use strict\";\r\n\r\n\r\n\r\n\r\n\r\n  var root = document.getElementById(\"tbt-sommelier\");\r\n\r\n\r\n\r\n  if (!root) return;\r\n\r\n\r\n\r\n\r\n\r\n  var PER_CATEGORY = 3;\r\n\r\n\r\n\r\n  \/\/ ---------------------------------------------------------------------\r\n\r\n\r\n\r\n  \/\/ DATA \u2014 foods\r\n\r\n\r\n\r\n  \/\/ ---------------------------------------------------------------------\r\n\r\n\r\n\r\n  var FOODS = [\r\n\r\n\r\n\r\n    { id:\"asado\", label:\"Grilled Meats & BBQ\" },\r\n\r\n\r\n\r\n    { id:\"bbq-ahumado\", label:\"BBQ & Smoked Meats\" },\r\n\r\n\r\n\r\n    { id:\"brasa\", label:\"Grilled over Embers\" },\r\n\r\n\r\n\r\n    { id:\"carnes-rojas\", label:\"Red Meats\" },\r\n\r\n\r\n\r\n    { id:\"cerdo\", label:\"Pork\" },\r\n\r\n\r\n\r\n    { id:\"pollo\", label:\"Chicken & Poultry\" },\r\n\r\n\r\n\r\n    { id:\"pato\", label:\"Duck\" },\r\n\r\n\r\n\r\n    { id:\"caza\", label:\"Game (rabbit, wild boar, venison)\" },\r\n\r\n\r\n\r\n    { id:\"marinados-especiados\", label:\"Marinated & Spiced Meats\" },\r\n\r\n\r\n\r\n    { id:\"embutidos\", label:\"Charcuterie & Cured Meats\" },\r\n\r\n\r\n\r\n    { id:\"pescados-blancos\", label:\"White Fish\" },\r\n\r\n\r\n\r\n    { id:\"pescados-azules\", label:\"Oily Fish\" },\r\n\r\n\r\n\r\n    { id:\"mariscos\", label:\"Seafood\" },\r\n\r\n\r\n\r\n    { id:\"pescados-ahumados\", label:\"Smoked Fish\" },\r\n\r\n\r\n\r\n    { id:\"sushi\", label:\"Sushi & Raw Fish\" },\r\n\r\n\r\n\r\n    { id:\"ceviche\", label:\"Ceviche\" },\r\n\r\n\r\n\r\n    { id:\"pastas\", label:\"Pasta (with red, white, or mixed sauce)\" },\r\n\r\n\r\n\r\n    { id:\"pizza\", label:\"Pizza\" },\r\n\r\n\r\n\r\n    { id:\"panaderia\", label:\"Bakery & Artisan Bread\" },\r\n\r\n\r\n\r\n    { id:\"paella-arroces-secos\", label:\"Paella & Dry Rice Dishes\" },\r\n\r\n\r\n\r\n    { id:\"arroces-caldosos\", label:\"Brothy Rice Dishes\" },\r\n\r\n\r\n\r\n    { id:\"legumbres\", label:\"Legumes (lentils, chickpeas, beans)\" },\r\n\r\n\r\n\r\n    { id:\"guisos-legumbres\", label:\"Legume Stews\" },\r\n\r\n\r\n\r\n    { id:\"hamburguesas\", label:\"Burgers\" },\r\n\r\n\r\n\r\n    { id:\"frituras\", label:\"Fried Foods & Fast Food\" },\r\n\r\n\r\n\r\n    { id:\"perros-calientes\", label:\"Hot Dogs\" },\r\n\r\n\r\n\r\n    { id:\"snacks-salados\", label:\"Popcorn & Savory Snacks\" },\r\n\r\n\r\n\r\n    { id:\"ensaladas\", label:\"Salads & Vegetables\" },\r\n\r\n\r\n\r\n    { id:\"vegetariano\", label:\"Vegetarian Dishes\" },\r\n\r\n\r\n\r\n    { id:\"verduras-asadas\", label:\"Roasted Vegetables\" },\r\n\r\n\r\n\r\n    { id:\"sopas-guisos\", label:\"Soups & Light Stews\" },\r\n\r\n\r\n\r\n    { id:\"estofados-carne\", label:\"Meat Stews (beef, lamb)\" },\r\n\r\n\r\n\r\n    { id:\"cocidos-pucheros\", label:\"Hearty Stews & Pot-au-Feu\" },\r\n\r\n\r\n\r\n    { id:\"fabadas-potajes\", label:\"Fabada & Bean Stews\" },\r\n\r\n\r\n\r\n    { id:\"chili-con-carne\", label:\"Chili con Carne\" },\r\n\r\n\r\n\r\n    { id:\"gazpacho-salmorejo\", label:\"Gazpacho & Salmorejo\" },\r\n\r\n\r\n\r\n    { id:\"ensaladilla-rusa\", label:\"Russian Salad & Pasta Salads\" },\r\n\r\n\r\n\r\n    { id:\"empanadas-pasteles-salados\", label:\"Empanadas & Savory Pastries\" },\r\n\r\n\r\n\r\n    { id:\"pates-terrinas\", label:\"P\u00e2t\u00e9s & Terrines\" },\r\n\r\n\r\n\r\n    { id:\"huevos-revueltos-fritos\", label:\"Scrambled \/ Fried Eggs\" },\r\n\r\n\r\n\r\n    { id:\"tortillas\", label:\"Omelettes (Spanish, French)\" },\r\n\r\n\r\n\r\n    { id:\"huevos-poche-benedictino\", label:\"Poached Eggs \/ Benedict\" },\r\n\r\n\r\n\r\n    { id:\"frittatas-quiches\", label:\"Frittatas & Quiches\" },\r\n\r\n\r\n\r\n    { id:\"tapas-frias\", label:\"Cold Tapas\" },\r\n\r\n\r\n\r\n    { id:\"tapas-calientes\", label:\"Hot Tapas\" },\r\n\r\n\r\n\r\n    { id:\"aperitivos-variados\", label:\"Mixed Appetizers\" },\r\n\r\n\r\n\r\n    { id:\"picante\", label:\"Spicy Food\" },\r\n\r\n\r\n\r\n    { id:\"curry\", label:\"Curry\" },\r\n\r\n\r\n\r\n    { id:\"asiatica\", label:\"Stir-Fried Asian Food\" },\r\n\r\n\r\n\r\n    { id:\"cocina-hindu\", label:\"Indian Cuisine\" },\r\n\r\n\r\n\r\n    { id:\"quesos-frescos\", label:\"Fresh Cheeses\" },\r\n\r\n\r\n\r\n    { id:\"quesos-curados\", label:\"Aged Cheeses\" },\r\n\r\n\r\n\r\n    { id:\"quesos-azules\", label:\"Blue Cheeses\" },\r\n\r\n\r\n\r\n    { id:\"frutos-secos-aceitunas\", label:\"Nuts & Olives\" },\r\n\r\n\r\n\r\n    { id:\"salsas\", label:\"Sauces (mayonnaise, aioli, chimichurri)\" },\r\n\r\n\r\n\r\n    { id:\"encurtidos\", label:\"Pickles (cucumbers, onions, capers)\" },\r\n\r\n\r\n\r\n    { id:\"mermeladas-conservas\", label:\"Jams & Preserves\" },\r\n\r\n\r\n\r\n    { id:\"postres-chocolate\", label:\"Chocolate Desserts\" },\r\n\r\n\r\n\r\n    { id:\"postres-frutales\", label:\"Fruit Desserts\" },\r\n\r\n\r\n\r\n    { id:\"postres-cremosos\", label:\"Creamy & Caramel Desserts\" },\r\n\r\n\r\n\r\n    { id:\"postres-especiados\", label:\"Spiced Desserts\" },\r\n\r\n\r\n\r\n    { id:\"helados-sorbetes\", label:\"Ice Cream & Sorbets\" },\r\n\r\n\r\n\r\n    { id:\"donuts-rosquillas\", label:\"Donuts & Doughnuts\" },\r\n\r\n\r\n\r\n    { id:\"galletas\", label:\"Cookies (butter, oatmeal, chocolate chip)\" },\r\n\r\n\r\n\r\n    { id:\"pasteles-esponjosos\", label:\"Muffins & Sponge Cakes\" }\r\n\r\n\r\n\r\n  ];\r\n\r\n\r\n\r\n  \/\/ ---------------------------------------------------------------------\r\n\r\n\r\n\r\n  \/\/ DATA \u2014 all 93 BJCP 2021 styles with fixed ABV\/IBU\/color stats\r\n\r\n\r\n\r\n  \/\/ (the remaining 17 of the 110 guidelines are open specialty\r\n\r\n\r\n\r\n  \/\/ templates without a fixed numerical range, left out on purpose).\r\n\r\n\r\n\r\n  \/\/ bitterness\/roast\/strength\/sour\/wheat\/belgian\/smoked\/fruit are\r\n\r\n\r\n\r\n  \/\/ calculated attributes from IBU, color, and official category, used\r\n\r\n\r\n\r\n  \/\/ by the rule engine below.\r\n\r\n\r\n\r\n  \/\/ ---------------------------------------------------------------------\r\n\r\n\r\n\r\n  var STYLES = [\r\n\r\n\r\n\r\n    { id:\"american-light-lager\", label:\"American Light Lager\", abv:\"2.8\u20134.2%\", ibu:\"8\u201312\", bitterness:\"low\", roast:\"pale\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"american-lager\", label:\"American Lager\", abv:\"4.2\u20135.3%\", ibu:\"8\u201318\", bitterness:\"low\", roast:\"pale\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"cream-ale\", label:\"Cream Ale\", abv:\"4.2\u20135.6%\", ibu:\"8\u201320\", bitterness:\"low\", roast:\"pale\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"american-wheat-beer\", label:\"American Wheat Beer\", abv:\"4\u20135.5%\", ibu:\"15\u201330\", bitterness:\"med\", roast:\"pale\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"international-pale-lager\", label:\"International Pale Lager\", abv:\"4.5\u20136%\", ibu:\"18\u201325\", bitterness:\"med\", roast:\"pale\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"international-amber-lager\", label:\"International Amber Lager\", abv:\"4.5\u20136%\", ibu:\"8\u201325\", bitterness:\"low\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"international-dark-lager\", label:\"International Dark Lager\", abv:\"4.2\u20136%\", ibu:\"8\u201320\", bitterness:\"low\", roast:\"dark\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"czech-pale-lager\", label:\"Czech Pale Lager\", abv:\"3\u20134.1%\", ibu:\"20\u201335\", bitterness:\"med\", roast:\"pale\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"czech-premium-pale-lager\", label:\"Czech Premium Pale Lager\", abv:\"4.2\u20135.8%\", ibu:\"30\u201345\", bitterness:\"med\", roast:\"pale\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"czech-amber-lager\", label:\"Czech Amber Lager\", abv:\"4.4\u20135.8%\", ibu:\"20\u201335\", bitterness:\"med\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"czech-dark-lager\", label:\"Czech Dark Lager\", abv:\"4.4\u20135.8%\", ibu:\"18\u201334\", bitterness:\"med\", roast:\"dark\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"munich-helles\", label:\"Munich Helles\", abv:\"4.7\u20135.4%\", ibu:\"16\u201322\", bitterness:\"low\", roast:\"pale\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"festbier\", label:\"Festbier\", abv:\"5.8\u20136.3%\", ibu:\"18\u201325\", bitterness:\"med\", roast:\"pale\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"helles-bock\", label:\"Helles Bock\", abv:\"6.3\u20137.4%\", ibu:\"23\u201335\", bitterness:\"med\", roast:\"pale\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"german-leichtbier\", label:\"German Leichtbier\", abv:\"2.4\u20133.6%\", ibu:\"15\u201328\", bitterness:\"med\", roast:\"pale\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"kolsch\", label:\"K\u00f6lsch\", abv:\"4.4\u20135.2%\", ibu:\"18\u201330\", bitterness:\"med\", roast:\"pale\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"german-helles-exportbier\", label:\"German Helles Exportbier\", abv:\"5\u20136%\", ibu:\"20\u201330\", bitterness:\"med\", roast:\"pale\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"german-pils\", label:\"German Pils\", abv:\"4.4\u20135.2%\", ibu:\"22\u201340\", bitterness:\"med\", roast:\"pale\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"marzen\", label:\"M\u00e4rzen\", abv:\"5.6\u20136.3%\", ibu:\"18\u201324\", bitterness:\"med\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"rauchbier\", label:\"Rauchbier\", abv:\"4.8\u20136%\", ibu:\"20\u201330\", bitterness:\"med\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:true, fruit:false },\r\n\r\n\r\n\r\n    { id:\"dunkles-bock\", label:\"Dunkles Bock\", abv:\"6.3\u20137.2%\", ibu:\"20\u201327\", bitterness:\"med\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"vienna-lager\", label:\"Vienna Lager\", abv:\"4.7\u20135.5%\", ibu:\"18\u201330\", bitterness:\"med\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"altbier\", label:\"Altbier\", abv:\"4.3\u20135.5%\", ibu:\"25\u201350\", bitterness:\"med\", roast:\"amber\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"munich-dunkel\", label:\"Munich Dunkel\", abv:\"4.5\u20135.6%\", ibu:\"18\u201328\", bitterness:\"med\", roast:\"dark\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"schwarzbier\", label:\"Schwarzbier\", abv:\"4.4\u20135.4%\", ibu:\"20\u201335\", bitterness:\"med\", roast:\"dark\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"doppelbock\", label:\"Doppelbock\", abv:\"7\u201310%\", ibu:\"16\u201326\", bitterness:\"med\", roast:\"amber\", strength:\"strong\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"eisbock\", label:\"Eisbock\", abv:\"9\u201314%\", ibu:\"25\u201335\", bitterness:\"med\", roast:\"dark\", strength:\"veryStrong\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"baltic-porter\", label:\"Baltic Porter\", abv:\"6.5\u20139.5%\", ibu:\"20\u201340\", bitterness:\"med\", roast:\"dark\", strength:\"strong\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"weissbier\", label:\"Weissbier\", abv:\"4.3\u20135.6%\", ibu:\"8\u201315\", bitterness:\"low\", roast:\"pale\", strength:\"session\", sour:false, wheat:true, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"dunkles-weissbier\", label:\"Dunkles Weissbier\", abv:\"4.3\u20135.6%\", ibu:\"10\u201318\", bitterness:\"low\", roast:\"amber\", strength:\"session\", sour:false, wheat:true, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"weizenbock\", label:\"Weizenbock\", abv:\"6.5\u20139%\", ibu:\"15\u201330\", bitterness:\"med\", roast:\"amber\", strength:\"strong\", sour:false, wheat:true, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"ordinary-bitter\", label:\"Ordinary Bitter\", abv:\"3.2\u20133.8%\", ibu:\"25\u201335\", bitterness:\"med\", roast:\"amber\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"best-bitter\", label:\"Best Bitter\", abv:\"3.8\u20134.6%\", ibu:\"25\u201340\", bitterness:\"med\", roast:\"amber\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"strong-bitter\", label:\"Strong Bitter\", abv:\"4.6\u20136.2%\", ibu:\"30\u201350\", bitterness:\"high\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"british-golden-ale\", label:\"British Golden Ale\", abv:\"3.8\u20135%\", ibu:\"20\u201345\", bitterness:\"med\", roast:\"pale\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"australian-sparkling-ale\", label:\"Australian Sparkling Ale\", abv:\"4.5\u20136%\", ibu:\"20\u201335\", bitterness:\"med\", roast:\"pale\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"english-ipa\", label:\"English IPA\", abv:\"5\u20137.5%\", ibu:\"40\u201360\", bitterness:\"high\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"dark-mild\", label:\"Dark Mild\", abv:\"3\u20133.8%\", ibu:\"10\u201325\", bitterness:\"low\", roast:\"amber\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"british-brown-ale\", label:\"British Brown Ale\", abv:\"4.2\u20135.9%\", ibu:\"20\u201330\", bitterness:\"med\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"english-porter\", label:\"English Porter\", abv:\"4\u20135.4%\", ibu:\"18\u201335\", bitterness:\"med\", roast:\"dark\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"scottish-light\", label:\"Scottish Light\", abv:\"2.5\u20133.3%\", ibu:\"10\u201320\", bitterness:\"low\", roast:\"dark\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"scottish-heavy\", label:\"Scottish Heavy\", abv:\"3.3\u20133.9%\", ibu:\"10\u201320\", bitterness:\"low\", roast:\"amber\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"scottish-export\", label:\"Scottish Export\", abv:\"3.9\u20136%\", ibu:\"15\u201330\", bitterness:\"med\", roast:\"amber\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"irish-red-ale\", label:\"Irish Red Ale\", abv:\"3.8\u20135%\", ibu:\"18\u201328\", bitterness:\"med\", roast:\"amber\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"irish-stout\", label:\"Irish Stout\", abv:\"3.8\u20135%\", ibu:\"25\u201345\", bitterness:\"med\", roast:\"dark\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"irish-extra-stout\", label:\"Irish Extra Stout\", abv:\"5\u20136.5%\", ibu:\"35\u201350\", bitterness:\"high\", roast:\"dark\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"sweet-stout\", label:\"Sweet Stout\", abv:\"4\u20136%\", ibu:\"20\u201340\", bitterness:\"med\", roast:\"dark\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"oatmeal-stout\", label:\"Oatmeal Stout\", abv:\"4.2\u20135.9%\", ibu:\"25\u201340\", bitterness:\"med\", roast:\"dark\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"tropical-stout\", label:\"Tropical Stout\", abv:\"5.5\u20138%\", ibu:\"30\u201350\", bitterness:\"high\", roast:\"dark\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"foreign-extra-stout\", label:\"Foreign Extra Stout\", abv:\"6.3\u20138%\", ibu:\"50\u201370\", bitterness:\"high\", roast:\"dark\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"british-strong-ale\", label:\"British Strong Ale\", abv:\"5.5\u20138%\", ibu:\"30\u201360\", bitterness:\"high\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"old-ale\", label:\"Old Ale\", abv:\"5.5\u20139%\", ibu:\"30\u201360\", bitterness:\"high\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"wee-heavy\", label:\"Wee Heavy\", abv:\"6.5\u201310%\", ibu:\"17\u201335\", bitterness:\"med\", roast:\"amber\", strength:\"strong\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"english-barley-wine\", label:\"English Barley Wine\", abv:\"8\u201312%\", ibu:\"35\u201370\", bitterness:\"high\", roast:\"amber\", strength:\"veryStrong\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"blonde-ale\", label:\"Blonde Ale\", abv:\"3.8\u20135.5%\", ibu:\"15\u201328\", bitterness:\"med\", roast:\"pale\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"american-pale-ale\", label:\"American Pale Ale\", abv:\"4.5\u20136.2%\", ibu:\"30\u201350\", bitterness:\"high\", roast:\"pale\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"american-amber-ale\", label:\"American Amber Ale\", abv:\"4.5\u20136.2%\", ibu:\"25\u201340\", bitterness:\"med\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"california-common\", label:\"California Common\", abv:\"4.5\u20135.5%\", ibu:\"30\u201345\", bitterness:\"med\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"american-brown-ale\", label:\"American Brown Ale\", abv:\"4.3\u20136.2%\", ibu:\"20\u201330\", bitterness:\"med\", roast:\"dark\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"american-porter\", label:\"American Porter\", abv:\"4.8\u20136.5%\", ibu:\"25\u201350\", bitterness:\"med\", roast:\"dark\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"american-stout\", label:\"American Stout\", abv:\"5\u20137%\", ibu:\"35\u201375\", bitterness:\"high\", roast:\"dark\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"imperial-stout\", label:\"Imperial Stout\", abv:\"8\u201312%\", ibu:\"50\u201390\", bitterness:\"high\", roast:\"dark\", strength:\"veryStrong\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"american-ipa\", label:\"American IPA\", abv:\"5.5\u20137.5%\", ibu:\"40\u201370\", bitterness:\"high\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"specialty-ipa\", label:\"Specialty IPA\", abv:\"5.5\u20139%\", ibu:\"50\u201390\", bitterness:\"high\", roast:\"dark\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"hazy-ipa\", label:\"Hazy IPA\", abv:\"6\u20139%\", ibu:\"25\u201360\", bitterness:\"high\", roast:\"pale\", strength:\"strong\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"double-ipa\", label:\"Double IPA\", abv:\"7.5\u201310%\", ibu:\"60\u2013100\", bitterness:\"high\", roast:\"amber\", strength:\"strong\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"american-strong-ale\", label:\"American Strong Ale\", abv:\"6.3\u201310%\", ibu:\"50\u2013100\", bitterness:\"high\", roast:\"amber\", strength:\"strong\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"american-barleywine\", label:\"American Barleywine\", abv:\"8\u201312%\", ibu:\"50\u2013100\", bitterness:\"high\", roast:\"amber\", strength:\"veryStrong\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"wheatwine\", label:\"Wheatwine\", abv:\"8\u201312%\", ibu:\"30\u201360\", bitterness:\"high\", roast:\"amber\", strength:\"veryStrong\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"berliner-weisse\", label:\"Berliner Weisse\", abv:\"2.8\u20133.8%\", ibu:\"3\u20138\", bitterness:\"low\", roast:\"pale\", strength:\"session\", sour:true, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"flanders-red-ale\", label:\"Flanders Red Ale\", abv:\"4.6\u20136.5%\", ibu:\"10\u201325\", bitterness:\"low\", roast:\"amber\", strength:\"standard\", sour:true, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"oud-bruin\", label:\"Oud Bruin\", abv:\"4\u20138%\", ibu:\"20\u201325\", bitterness:\"med\", roast:\"amber\", strength:\"standard\", sour:true, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"lambic\", label:\"Lambic\", abv:\"5\u20136.5%\", ibu:\"0\u201310\", bitterness:\"low\", roast:\"pale\", strength:\"standard\", sour:true, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"gueuze\", label:\"Gueuze\", abv:\"5\u20138%\", ibu:\"0\u201310\", bitterness:\"low\", roast:\"pale\", strength:\"standard\", sour:true, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"fruit-lambic\", label:\"Fruit Lambic\", abv:\"5\u20137%\", ibu:\"0\u201310\", bitterness:\"low\", roast:\"pale\", strength:\"standard\", sour:true, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"gose\", label:\"Gose\", abv:\"4.2\u20134.8%\", ibu:\"5\u201312\", bitterness:\"low\", roast:\"pale\", strength:\"session\", sour:true, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"witbier\", label:\"Witbier\", abv:\"4.5\u20135.5%\", ibu:\"8\u201320\", bitterness:\"low\", roast:\"pale\", strength:\"standard\", sour:false, wheat:false, belgian:true, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"belgian-pale-ale\", label:\"Belgian Pale Ale\", abv:\"4.8\u20135.5%\", ibu:\"20\u201330\", bitterness:\"med\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:true, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"biere-de-garde\", label:\"Bi\u00e8re de Garde\", abv:\"6\u20138.5%\", ibu:\"18\u201328\", bitterness:\"med\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:true, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"belgian-blond-ale\", label:\"Belgian Blond Ale\", abv:\"6\u20137.5%\", ibu:\"15\u201330\", bitterness:\"med\", roast:\"pale\", strength:\"standard\", sour:false, wheat:false, belgian:true, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"saison\", label:\"Saison\", abv:\"5\u20137%\", ibu:\"20\u201335\", bitterness:\"med\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:true, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"belgian-golden-strong-ale\", label:\"Belgian Golden Strong Ale\", abv:\"7.5\u201310.5%\", ibu:\"22\u201335\", bitterness:\"med\", roast:\"pale\", strength:\"strong\", sour:false, wheat:false, belgian:true, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"belgian-single\", label:\"Belgian Single\", abv:\"4.8\u20136%\", ibu:\"25\u201345\", bitterness:\"med\", roast:\"pale\", strength:\"standard\", sour:false, wheat:false, belgian:true, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"belgian-dubbel\", label:\"Belgian Dubbel\", abv:\"6\u20137.6%\", ibu:\"15\u201325\", bitterness:\"med\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:true, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"belgian-tripel\", label:\"Belgian Tripel\", abv:\"7.5\u20139.5%\", ibu:\"20\u201340\", bitterness:\"med\", roast:\"pale\", strength:\"strong\", sour:false, wheat:false, belgian:true, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"belgian-dark-strong-ale\", label:\"Belgian Dark Strong Ale\", abv:\"8\u201312%\", ibu:\"20\u201335\", bitterness:\"med\", roast:\"amber\", strength:\"veryStrong\", sour:false, wheat:false, belgian:true, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"straight-sour-beer\", label:\"Straight Sour Beer\", abv:\"4.5\u20137%\", ibu:\"3\u20138\", bitterness:\"low\", roast:\"pale\", strength:\"standard\", sour:true, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"grape-ale\", label:\"Grape Ale\", abv:\"6\u20138.5%\", ibu:\"10\u201330\", bitterness:\"med\", roast:\"pale\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:true },\r\n\r\n\r\n\r\n    { id:\"dorada-pampeana\", label:\"Dorada Pampeana\", abv:\"4.3\u20135.5%\", ibu:\"15\u201322\", bitterness:\"low\", roast:\"pale\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"ipa-argenta\", label:\"IPA Argenta\", abv:\"5\u20136.5%\", ibu:\"35\u201360\", bitterness:\"high\", roast:\"amber\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"italian-grape-ale\", label:\"Italian Grape Ale\", abv:\"4.5\u201312%\", ibu:\"6\u201330\", bitterness:\"low\", roast:\"amber\", strength:\"strong\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"catharina-sour\", label:\"Catharina Sour\", abv:\"4\u20135.5%\", ibu:\"2\u20138\", bitterness:\"low\", roast:\"pale\", strength:\"session\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false },\r\n\r\n\r\n\r\n    { id:\"new-zealand-pilsner\", label:\"New Zealand Pilsner\", abv:\"4.5\u20135.8%\", ibu:\"25\u201345\", bitterness:\"med\", roast:\"pale\", strength:\"standard\", sour:false, wheat:false, belgian:false, smoked:false, fruit:false }\r\n\r\n\r\n\r\n  ];\r\n\r\n\r\n\r\n  \/\/ ---------------------------------------------------------------------\r\n\r\n\r\n\r\n  \/\/ PAIRING ENGINE BY ATTRIBUTES \u2014 each food defines three independent\r\n\r\n\r\n\r\n  \/\/ rules, one per principle (affinity, contrast, complement),\r\n\r\n\r\n\r\n  \/\/ evaluated against the 93 styles. Not a closed list of pairs,\r\n\r\n\r\n\r\n  \/\/ any new style added to STYLES is automatically available for all\r\n\r\n\r\n\r\n  \/\/ three without touching this section.\r\n\r\n\r\n\r\n  \/\/ ---------------------------------------------------------------------\r\n\r\n\r\n\r\n  var CATS = [\"afinidad\", \"contraste\", \"complemento\"];\r\n\r\n\r\n\r\n\r\n\r\n  var RULES = {\r\n\r\n\r\n\r\n    \"asado\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.smoked || s.roast===\"dark\"; },\r\n\r\n\r\n\r\n        text:function(s){ return s.smoked ? \"The style's smoky character directly dialogues with grill smoke.\" : \"The malt toast echoes the toastiness and smoke of the grill.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Pronounced bitterness cuts through the fat of intense grilled cuts.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body and high carbonation refresh during a long barbecue without filling you up.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"bbq-ahumado\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.smoked; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's smoky character directly dialogues with slow-cooking smoke.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness cuts through the fat of a long, unctuous cooking process.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Malt toast accompanies smoky flavor without competing.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"brasa\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium toasted profile echoes the golden sear and ember marks.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness cuts through the fat of ember-cooked meat.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body accompanies ember-grilled meat without overwhelming it.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"carnes-rojas\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Malt toast echoes the sear and crust of red meat.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness and carbonation cut through the fat of juicy red meat.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium toasted profile accompanies the meat without overwhelming it.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"cerdo\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Ripe fruit sweetness and Belgian esters accompany typical pork sauces and glazes.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\" || s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness cuts through pork fat.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium toasted profile combines with golden glazes and sauces.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"pollo\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.wheat; },\r\n\r\n\r\n\r\n        text:function(){ return \"Wheat's fruity esters combine with chicken prepared with mild spices.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return (s.bitterness===\"med\" || s.bitterness===\"high\") && s.roast!==\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness cuts through the fat of fried or glazed chicken.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"low\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body and low bitterness do not overshadow delicate chicken.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"pato\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.fruit; },\r\n\r\n\r\n\r\n        text:function(){ return \"Fruity notes echo the fruit sauce typical of duck.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity cuts through the rich fat of duck.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"strong\" || s.strength===\"veryStrong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dense body matches the intensity of duck.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"caza\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"dark\" || s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dark toast or Belgian spiced sweetness echoes the intense flavor of game.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity cuts through the fat and strong flavor of game meat.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"strong\" || s.strength===\"veryStrong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dense body matches the intensity of game meat.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"marinados-especiados\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.smoked; },\r\n\r\n\r\n\r\n        text:function(){ return \"Smoked or toasted character echoes a spiced marinade on the grill.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"High bitterness cuts through the fat of marinated cuts.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body accompanies marinated meat without overwhelming it.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"embutidos\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dark fruit and caramel notes accompany the cured fat of charcuterie.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"high\" || s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness or acidity cuts through the cured fat of charcuterie.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body accompanies charcuterie without competing with its saltiness.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"pescados-blancos\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Citrus or floral hop notes echo the lemon that often accompanies white fish.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's acidity contrasts with the natural sweetness of white fish.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"low\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body does not overshadow delicate white fish.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"pescados-azules\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Citrus or floral hop notes echo the lemon that cuts through oily fish fat.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\" || s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness or acidity cuts through the natural fat of oily fish.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body accompanies the more intense flavor of oily fish.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"mariscos\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Citrus or floral hop notes echo the lemon that often accompanies seafood.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's acidity contrasts with the natural sweetness of seafood.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.bitterness!==\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light profile and fine carbonation enhance seafood's saltiness without masking it.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"pescados-ahumados\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.smoked; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's smoky character echoes smoked fish.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity cuts through the unctuousness of smoked fish.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"low\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body does not overshadow smoked fish.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"sushi\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity plays a role similar to rice vinegar.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness cleans the fat of cuts like salmon or fatty tuna.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"low\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body and low intensity let the raw fish take center stage.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"ceviche\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity echoes the citrus of ceviche.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness cuts through the natural oil of raw fish.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"low\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body does not overshadow delicate ceviche.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"pastas\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Ripe fruit sweetness combines with meat-stuffed pasta and reduced sauces.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\" && s.roast!==\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness balances tomato-based sauces.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"low\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light profile does not compete with simple oil-and-garlic pasta.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"pizza\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Malt toast echoes a well-baked crust or smoked cured meats.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\" && s.roast!==\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness cuts through melted cheese fat.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Toasted profile accompanies the crust without competing with other ingredients.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"panaderia\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Belgian esters echo the caramelized crust of artisan bread.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness cuts through butter spread on bread.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium toast echoes the crust without competing.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"paella-arroces-secos\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium toasted profile echoes the socarrat and sofrito of paella or dry rice.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\" || s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness or acidity cuts through the oil of the sofrito.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Citrus freshness of hops accompanies the variety of ingredients without masking them.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"arroces-caldosos\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium toasted profile echoes the depth of a reduced broth.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness cuts through the unctuousness of brothy rice.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"session\" || s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light to medium body does not overshadow a delicate broth.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"legumbres\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dark toast echoes the earthy character of legumes.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness lightens the density of a legume dish.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body accompanies legumes without dominating them.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"guisos-legumbres\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.smoked || s.roast===\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Smoked or toasted character echoes the chorizo or blood sausage in a legume stew.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness cuts through the fat of legume stew with cured meat.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body matches the intensity of a legume stew.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"hamburguesas\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Malt toast accompanies meats with smoky notes.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Resinous bitterness cuts through the fat of the meat and melted cheese.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body accompanies the burger without competing with the bun or lettuce.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"frituras\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's toasted profile echoes the golden brown of fried food.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\" || s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness cuts through the fat of fried food.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Lightness and high carbonation cleanse the palate between bites of fried food.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"perros-calientes\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Toasted profile echoes the grilled or griddled sausage.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\" || s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness cuts through sausage fat and the sweet sauces of a hot dog.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light, refreshing body accompanies fast food without adding more weight.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"snacks-salados\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium toast echoes the toasted corn of a savory snack.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\" || s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness cuts through the fat of fried items and butter.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body refreshes between bites of savory snacks.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"ensaladas\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's acidity echoes the vinegar of a fresh dressing.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\" || s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness cuts through the creaminess of a Caesar or ranch dressing.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light, refreshing profile does not overshadow raw vegetables or citrus dressings.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"vegetariano\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.wheat || s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Fruity or spiced notes combine with roasted vegetables and fresh herbs.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness contrasts with the natural sweetness of roasted or glazed vegetables.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"low\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body does not overshadow delicate vegetable flavors.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"verduras-asadas\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's toasted profile echoes the caramelization of roasted vegetables.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness contrasts with the sweetness of oven-caramelized vegetables.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"low\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body does not overshadow the natural flavor of roasted vegetables.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"sopas-guisos\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dark toast echoes a slow-cooked soup or stew.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness cuts through the unctuousness of a thick soup.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body accompanies a mild soup without adding more weight.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"estofados-carne\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dark toast echoes the depth of a slow-cooked meat stew.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness cuts through the unctuousness of a meat stew.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"standard\" || s.strength===\"strong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dense body matches the intensity of beef or lamb stew.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"cocidos-pucheros\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.smoked || s.roast===\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Smoked or toasted character echoes the chorizo or blood sausage in a hearty stew.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\" || s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness cuts through the fat of meats in a hearty stew or pot-au-feu.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body accompanies a hearty stew without overwhelming it.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"fabadas-potajes\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.smoked; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's smoky character echoes the chorizo and blood sausage in fabada.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"High bitterness cuts through the dense fat of fabada.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"dark\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dark toast and medium body match the richness of a legume pot stew.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"chili-con-carne\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dark toast echoes the meat and paprika in chili con carne.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"low\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Low bitterness refreshes the palate without adding more heat to the chili.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body matches the intensity of chili con carne.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"gazpacho-salmorejo\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's acidity echoes the tomato and vinegar of gazpacho or salmorejo.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness cuts through the olive oil of a cold soup.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light, refreshing body accompanies a cold soup without adding weight.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"ensaladilla-rusa\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Citrus hop notes echo the tuna and pickles in a Russian salad.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity cuts through the mayonnaise of Russian salad.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body does not overshadow a cold mayonnaise-based salad.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"empanadas-pasteles-salados\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Toasted profile echoes a baked or fried pastry crust.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\" || s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness cuts through the fat of the pastry and filling.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body accompanies an empanada or savory pastry without overwhelming it.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"pates-terrinas\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.belgian || s.fruit; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's fruity sweetness echoes the quince paste or jam that often accompanies p\u00e2t\u00e9.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour || s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity or bitterness cuts through the dense fat of p\u00e2t\u00e9 or terrine.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"strong\" || s.strength===\"veryStrong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dense body matches the richness of p\u00e2t\u00e9.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"huevos-revueltos-fritos\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's toasted profile echoes the richness of egg yolk.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness cuts through yolk fat.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body does not overshadow a simple egg dish.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"tortillas\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium toasted profile echoes the caramelized onion or potato in an omelette.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness cuts through the fat of egg and potato.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"low\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body does not overshadow a simple omelette.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"huevos-poche-benedictino\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Citrus hop notes echo the lemon in hollandaise sauce.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity cuts through the fat of hollandaise sauce.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body does not compete with delicate poached eggs.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"frittatas-quiches\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.wheat || s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Fruity or spiced notes combine with the herbs and vegetables in a quiche.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness cuts through the fat of cheese and cream in a frittata or quiche.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body accompanies a frittata or quiche without overwhelming it.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"tapas-frias\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Citrus hop freshness echoes ham, cheese, or cold tapas.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity cuts through the fat and salt of cured meats or aged cheese.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body accompanies a variety of cold tapas without dominating any.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"tapas-calientes\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"amber\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Toasted profile echoes the golden brown of croquettes or fried calamari.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\" || s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness cuts through the fat of fried tapas.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body accompanies a variety of hot tapas.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"aperitivos-variados\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Belgian esters accompany the variety of flavors on an appetizer board.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"high\" || s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness or acidity cuts through the fat and salt of fried items and savory bites.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body accompanies mixed appetizers without competing.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"picante\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's spiced notes echo the spices in a spicy dish.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"low\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Low bitterness refreshes the palate without adding more heat to the spice.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body does not add more intensity to an already spicy dish.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"curry\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.belgian || s.wheat; },\r\n\r\n\r\n\r\n        text:function(){ return \"Spiced and fruity notes combine with curry spices.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity cuts through the unctuousness of a creamy curry sauce.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"low\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light profile does not compete with curry spices.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"asiatica\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.wheat || s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Fruity notes or acidity dialogue with sweet-and-sour flavors.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity cuts through the fat of soy- or sesame-oil-based sauces.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.bitterness===\"low\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light, clean profile does not compete with soy, ginger, or sesame sauces.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"cocina-hindu\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.belgian || s.wheat; },\r\n\r\n\r\n\r\n        text:function(){ return \"Spiced and fruity notes echo the spices of Indian cuisine.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity cuts through the unctuousness of ghee and creamy sauces.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.bitterness===\"low\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light profile does not compete with the spice layer of an Indian dish.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"quesos-frescos\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.wheat; },\r\n\r\n\r\n\r\n        text:function(){ return \"Wheat's mild character echoes the creaminess of fresh cheese.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity contrasts with the creaminess of fresh cheese.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light body does not overshadow delicate fresh cheese.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"quesos-curados\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dark fruit notes accompany intense aged cheese.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity contrasts with the density of aged cheese.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"strong\" || s.strength===\"veryStrong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Body and alcoholic sweetness balance aged or hard-paste cheese.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"quesos-azules\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.fruit; },\r\n\r\n\r\n\r\n        text:function(){ return \"Fruity sweetness echoes the honey or jam that often accompanies blue cheese.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.strength===\"strong\" || s.strength===\"veryStrong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Sweetness and dense body of an intense style balance the salt and pungency of blue cheese.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Belgian esters accompany blue cheese without being overshadowed by its intensity.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"frutos-secos-aceitunas\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Belgian esters echo toasted nuts.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity cuts through the oiliness of olives.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body accompanies nuts and olives without competing.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"salsas\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's acidity echoes a vinegar-based sauce like mojo or chimichurri.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"high\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Bitterness cuts through the fat of a mayonnaise-based sauce like aioli or brava.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"amber\" && s.strength===\"standard\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Medium body accompanies a sauce without competing with the main dish.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"encurtidos\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"The style's acidity echoes the vinegar of pickles.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness balances the acidity of pickles.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.roast===\"pale\" && s.strength===\"session\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Light, crisp body does not compete with pickles.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"mermeladas-conservas\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.fruit; },\r\n\r\n\r\n\r\n        text:function(){ return \"Fruity notes echo fruit jam or preserves.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity balances the sweetness of jam or preserves.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"standard\" || s.strength===\"strong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Body and sweetness accompany jam or preserves without masking them.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"postres-chocolate\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"dark\" && (s.strength===\"strong\" || s.strength===\"veryStrong\"); },\r\n\r\n\r\n\r\n        text:function(){ return \"Intense sweetness and coffee or chocolate notes of a dark, strong style accompany the chocolate.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity balances the sweetness of an intense chocolate dessert.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"strong\" || s.strength===\"veryStrong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dense body and sweetness accompany a chocolate dessert without competing.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"postres-frutales\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.fruit; },\r\n\r\n\r\n\r\n        text:function(){ return \"Fruity notes echo the fruit in the dessert.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity balances the sweetness of a fruit dessert.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"standard\" || s.strength===\"strong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Body and sweetness accompany a fruit dessert without masking it.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"postres-cremosos\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Ripe fruit and caramel sweetness echo a creamy dessert or dulce de leche.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity cuts through the unctuousness of a creamy dessert.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"strong\" || s.strength===\"veryStrong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dense body accompanies a creamy dessert without competing.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"postres-especiados\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Belgian esters echo cinnamon, ginger, or nutmeg.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity balances the sweetness of a spiced dessert.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"strong\" || s.strength===\"veryStrong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dense body matches the intensity of a spiced dessert.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"helados-sorbetes\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.fruit; },\r\n\r\n\r\n\r\n        text:function(){ return \"Fruity notes echo a fruit sorbet.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.bitterness===\"med\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Moderate bitterness cuts through the fat and sweetness of creamy ice cream.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"strong\" || s.strength===\"veryStrong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dense body and sweetness accompany an ice cream float-style dessert.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"donuts-rosquillas\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"dark\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Dark toast echoes the caramelized glaze of a doughnut.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity cuts through the sweetness and fat of fried dough.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"strong\" || s.strength===\"veryStrong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Sweetness and body accompany a doughnut without being overshadowed.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"galletas\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.roast===\"dark\" && (s.strength===\"strong\" || s.strength===\"veryStrong\"); },\r\n\r\n\r\n\r\n        text:function(){ return \"Caramel, coffee, or chocolate notes of a dark, strong style echo a baked cookie.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity balances the sweetness of a cookie.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"strong\" || s.strength===\"veryStrong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Sweetness and body accompany a cookie without competing.\"; } }\r\n\r\n\r\n\r\n    },\r\n\r\n\r\n\r\n    \"pasteles-esponjosos\": {\r\n\r\n\r\n\r\n      afinidad: { test:function(s){ return s.fruit || s.belgian; },\r\n\r\n\r\n\r\n        text:function(){ return \"Fruity or spiced notes echo the citrus zest of a sponge cake or muffin.\"; } },\r\n\r\n\r\n\r\n      contraste: { test:function(s){ return s.sour; },\r\n\r\n\r\n\r\n        text:function(){ return \"Acidity cuts through the sweetness of a sponge cake.\"; } },\r\n\r\n\r\n\r\n      complemento: { test:function(s){ return s.strength===\"standard\" || s.strength===\"strong\"; },\r\n\r\n\r\n\r\n        text:function(){ return \"Body and moderate sweetness accompany a sponge cake without masking it.\"; } }\r\n\r\n\r\n\r\n    }\r\n\r\n\r\n\r\n  };\r\n\r\n\r\n\r\n\r\n\r\n  var CAT_LABELS = { afinidad:\"Affinity\", contraste:\"Contrast\", complemento:\"Complement\" };\r\n\r\n\r\n\r\n  \/\/ ---------------------------------------------------------------------\r\n\r\n\r\n\r\n  \/\/ LEVEL A \u2014 beers reviewed by TBT that reinforce a recommendation.\r\n\r\n\r\n\r\n  \/\/ Empty on purpose. Fill only with verified data from the\r\n\r\n\r\n\r\n  \/\/ actual article (post_id, exact style as published).\r\n\r\n\r\n\r\n  \/\/ Format: { style:\"<id from STYLES>\", title:\"...\", postId: 0 }\r\n\r\n\r\n\r\n  \/\/ ---------------------------------------------------------------------\r\n\r\n\r\n\r\n  var REVIEWED_BEERS = [\r\n\r\n\r\n\r\n    { style:\"belgian-blond-ale\", title:\"Chimay Dor\u00e9e (Blonde)\", postId:49160 },\r\n\r\n\r\n\r\n    { style:\"weissbier\", title:\"Weihenstephaner Hefe Weissbier\", postId:44791 },\r\n\r\n\r\n\r\n    { style:\"double-ipa\", title:\"Pliny the Elder\", postId:44686 },\r\n\r\n\r\n\r\n    { style:\"gueuze\", title:\"3 Fonteinen Oude Geuze\", postId:49167 },\r\n\r\n\r\n\r\n    { style:\"international-pale-lager\", title:\"Stella Artois\", postId:42684 },\r\n\r\n\r\n\r\n    { style:\"vienna-lager\", title:\"Cerveza Indio\", postId:42456 },\r\n\r\n\r\n\r\n    { style:\"best-bitter\", title:\"Fuller\u2019s London Pride\", postId:17095 },\r\n\r\n\r\n\r\n    { style:\"munich-dunkel\", title:\"Negra Modelo Dunkel\", postId:34782 },\r\n\r\n\r\n\r\n    { style:\"belgian-dark-strong-ale\", title:\"St. Bernardus Abt 12\", postId:17125 },\r\n\r\n\r\n\r\n    { style:\"witbier\", title:\"Hoegaarden Wit\", postId:17008 },\r\n\r\n\r\n\r\n    { style:\"american-ipa\", title:\"Lagunitas IPA\", postId:16912 },\r\n\r\n\r\n\r\n    { style:\"english-ipa\", title:\"Goose Island IPA\", postId:16948 },\r\n\r\n\r\n\r\n    { style:\"imperial-stout\", title:\"Fuller\u2019s Imperial Stout\", postId:17074 },\r\n\r\n\r\n\r\n    { style:\"belgian-golden-strong-ale\", title:\"Duvel Belgian Strong Ale\", postId:17085 },\r\n\r\n\r\n\r\n    { style:\"rauchbier\", title:\"Schlenkerla Rauchbier\", postId:17080 },\r\n\r\n\r\n\r\n    { style:\"foreign-extra-stout\", title:\"Cuello Negro Stout\", postId:27905 },\r\n\r\n\r\n\r\n    { style:\"belgian-tripel\", title:\"Westmalle Tripel\", postId:16976 },\r\n\r\n\r\n\r\n    { style:\"belgian-pale-ale\", title:\"Orval Belgian Pale Ale\", postId:17110 },\r\n\r\n\r\n\r\n    { style:\"belgian-dubbel\", title:\"Westmalle Dubbel\", postId:27573 },\r\n\r\n\r\n\r\n    { style:\"saison\", title:\"Saison Dupont\", postId:17015 },\r\n\r\n\r\n\r\n    { style:\"american-porter\", title:\"Anchor Porter\", postId:17379 },\r\n\r\n\r\n\r\n    { style:\"czech-premium-pale-lager\", title:\"Pilsner Urquell\", postId:17115 },\r\n\r\n\r\n\r\n    { style:\"flanders-red-ale\", title:\"Petrus Aged Red\", postId:17182 },\r\n\r\n\r\n\r\n    { style:\"american-amber-ale\", title:\"Rogue American Amber Ale\", postId:17105 },\r\n\r\n\r\n\r\n    { style:\"american-lager\", title:\"Corona Extra\", postId:16917 },\r\n\r\n\r\n\r\n    { style:\"american-barleywine\", title:\"Sierra Nevada Bigfoot\", postId:17147 },\r\n\r\n\r\n\r\n    { style:\"schwarzbier\", title:\"K\u00f6stritzer Schwarzbier\", postId:17155 },\r\n\r\n\r\n\r\n    { style:\"wee-heavy\", title:\"Founders Backwoods Bastard\", postId:17376 }\r\n\r\n\r\n\r\n  ];\r\n\r\n\r\n\r\n  \/\/ ---------------------------------------------------------------------\r\n\r\n\r\n\r\n  \/\/ STATE AND RENDER\r\n\r\n\r\n\r\n  \/\/ ---------------------------------------------------------------------\r\n\r\n\r\n\r\n  var state = { mode:\"comida\", selectedId:null, filter:\"\" };\r\n\r\n\r\n\r\n\r\n\r\n  var tabsEl = root.querySelectorAll(\".tbt-som-tab\");\r\n\r\n\r\n\r\n  var searchInput = root.querySelector(\".tbt-som-search-input\");\r\n\r\n\r\n\r\n  var chipsEl = root.querySelector(\".tbt-som-chips\");\r\n\r\n\r\n\r\n  var resultsEl = root.querySelector(\".tbt-som-results\");\r\n\r\n\r\n\r\n\r\n\r\n  function itemsForMode(){ return state.mode === \"comida\" ? FOODS : STYLES; }\r\n\r\n\r\n\r\n\r\n\r\n  function renderChips(){\r\n\r\n\r\n\r\n    var items = itemsForMode();\r\n\r\n\r\n\r\n    chipsEl.innerHTML = \"\";\r\n\r\n\r\n\r\n    items.forEach(function(item){\r\n\r\n\r\n\r\n      var btn = document.createElement(\"button\");\r\n\r\n\r\n\r\n      btn.type = \"button\";\r\n\r\n\r\n\r\n      btn.className = \"tbt-som-chip\";\r\n\r\n\r\n\r\n      btn.textContent = item.label;\r\n\r\n\r\n\r\n      btn.dataset.id = item.id;\r\n\r\n\r\n\r\n      if (item.id === state.selectedId) btn.classList.add(\"is-selected\");\r\n\r\n\r\n\r\n      if (state.filter && item.label.toLowerCase().indexOf(state.filter) === -1) {\r\n\r\n\r\n\r\n        btn.classList.add(\"is-hidden\");\r\n\r\n\r\n\r\n      }\r\n\r\n\r\n\r\n      btn.addEventListener(\"click\", function(){\r\n\r\n\r\n\r\n        state.selectedId = item.id;\r\n\r\n\r\n\r\n        renderChips();\r\n\r\n\r\n\r\n        renderResults();\r\n\r\n\r\n\r\n      });\r\n\r\n\r\n\r\n      chipsEl.appendChild(btn);\r\n\r\n\r\n\r\n    });\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n\r\n\r\n  function findReviewed(styleId){\r\n\r\n\r\n\r\n    for (var i = 0; i < REVIEWED_BEERS.length; i++) {\r\n\r\n\r\n\r\n      if (REVIEWED_BEERS[i].style === styleId) return REVIEWED_BEERS[i];\r\n\r\n\r\n\r\n    }\r\n\r\n\r\n\r\n    return null;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n\r\n\r\n  function tagEl(cat){\r\n\r\n\r\n\r\n    var span = document.createElement(\"span\");\r\n\r\n\r\n\r\n    span.className = \"tbt-som-tag tbt-som-tag--\" + cat;\r\n\r\n\r\n\r\n    span.textContent = CAT_LABELS[cat] || cat;\r\n\r\n\r\n\r\n    return span;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n\r\n\r\n  function cardForStyle(style, info){\r\n\r\n\r\n\r\n    var reviewed = findReviewed(style.id);\r\n\r\n\r\n\r\n    var card = document.createElement(\"div\");\r\n\r\n\r\n\r\n    card.className = \"tbt-som-card tbt-som-card--\" + info.cat;\r\n\r\n\r\n\r\n\r\n\r\n    var head = document.createElement(\"div\");\r\n\r\n\r\n\r\n    head.className = \"tbt-som-card-head\";\r\n\r\n\r\n\r\n    var h3 = document.createElement(\"h3\");\r\n\r\n\r\n\r\n    h3.textContent = style.label;\r\n\r\n\r\n\r\n    head.appendChild(h3);\r\n\r\n\r\n\r\n    if (reviewed) {\r\n\r\n\r\n\r\n      var badge = document.createElement(\"a\");\r\n\r\n\r\n\r\n      badge.className = \"tbt-som-badge\";\r\n\r\n\r\n\r\n      badge.href = \"https:\/\/www.thebeertimes.com\/?p=\" + reviewed.postId;\r\n\r\n\r\n\r\n      badge.appendChild(document.createTextNode(reviewed.title));\r\n\r\n\r\n\r\n      head.appendChild(badge);\r\n\r\n\r\n\r\n    }\r\n\r\n\r\n\r\n    card.appendChild(head);\r\n\r\n\r\n\r\n\r\n\r\n    var attrs = document.createElement(\"div\");\r\n\r\n\r\n\r\n    attrs.className = \"tbt-som-attrs\";\r\n\r\n\r\n\r\n    attrs.innerHTML =\r\n\r\n\r\n\r\n      '<div><span class=\"k\">ABV<\/span><span class=\"v\">' + style.abv + '<\/span><\/div>' +\r\n\r\n\r\n\r\n      '<div><span class=\"k\">IBU<\/span><span class=\"v\">' + style.ibu + '<\/span><\/div>';\r\n\r\n\r\n\r\n    card.appendChild(attrs);\r\n\r\n\r\n\r\n\r\n\r\n    var p = document.createElement(\"p\");\r\n\r\n\r\n\r\n    p.className = \"tbt-som-why\";\r\n\r\n\r\n\r\n    p.appendChild(tagEl(info.cat));\r\n\r\n\r\n\r\n    p.appendChild(document.createElement(\"br\"));\r\n\r\n\r\n\r\n    p.appendChild(document.createTextNode(info.text));\r\n\r\n\r\n\r\n    card.appendChild(p);\r\n\r\n\r\n\r\n\r\n\r\n    card.appendChild(feedbackRow());\r\n\r\n\r\n\r\n    return card;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n\r\n\r\n  function cardForFood(food, info){\r\n\r\n\r\n\r\n    var card = document.createElement(\"div\");\r\n\r\n\r\n\r\n    card.className = \"tbt-som-card tbt-som-card--\" + info.cat;\r\n\r\n\r\n\r\n\r\n\r\n    var head = document.createElement(\"div\");\r\n\r\n\r\n\r\n    head.className = \"tbt-som-card-head\";\r\n\r\n\r\n\r\n    var h3 = document.createElement(\"h3\");\r\n\r\n\r\n\r\n    h3.textContent = food.label;\r\n\r\n\r\n\r\n    head.appendChild(h3);\r\n\r\n\r\n\r\n    card.appendChild(head);\r\n\r\n\r\n\r\n\r\n\r\n    var p = document.createElement(\"p\");\r\n\r\n\r\n\r\n    p.className = \"tbt-som-why\";\r\n\r\n\r\n\r\n    p.appendChild(tagEl(info.cat));\r\n\r\n\r\n\r\n    p.appendChild(document.createElement(\"br\"));\r\n\r\n\r\n\r\n    p.appendChild(document.createTextNode(info.text));\r\n\r\n\r\n\r\n    card.appendChild(p);\r\n\r\n\r\n\r\n\r\n\r\n    card.appendChild(feedbackRow());\r\n\r\n\r\n\r\n    return card;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n\r\n\r\n  function feedbackRow(){\r\n\r\n\r\n\r\n    var foot = document.createElement(\"div\");\r\n\r\n\r\n\r\n    foot.className = \"tbt-som-foot\";\r\n\r\n\r\n\r\n    var span = document.createElement(\"span\");\r\n\r\n\r\n\r\n    span.textContent = \"Was this recommendation helpful?\";\r\n\r\n\r\n\r\n    var fb = document.createElement(\"div\");\r\n\r\n\r\n\r\n    fb.className = \"tbt-som-fb\";\r\n\r\n\r\n\r\n    var yes = document.createElement(\"button\");\r\n\r\n\r\n\r\n    yes.type = \"button\"; yes.textContent = \"Yes\"; yes.className = \"tbt-som-fb-yes\";\r\n\r\n\r\n\r\n    var no = document.createElement(\"button\");\r\n\r\n\r\n\r\n    no.type = \"button\"; no.textContent = \"No\"; no.className = \"tbt-som-fb-no\";\r\n\r\n\r\n\r\n    function vote(chosen, other){\r\n\r\n\r\n\r\n      chosen.classList.add(\"is-voted\");\r\n\r\n\r\n\r\n      chosen.disabled = true;\r\n\r\n\r\n\r\n      other.disabled = true;\r\n\r\n\r\n\r\n      \/\/ TODO: send this vote to a real endpoint (WordPress REST, spreadsheet, etc.) when available \u2014 today only changes visual state.\r\n\r\n\r\n\r\n    }\r\n\r\n\r\n\r\n    yes.addEventListener(\"click\", function(){ vote(yes, no); });\r\n\r\n\r\n\r\n    no.addEventListener(\"click\", function(){ vote(no, yes); });\r\n\r\n\r\n\r\n    fb.appendChild(yes); fb.appendChild(no);\r\n\r\n\r\n\r\n    foot.appendChild(span); foot.appendChild(fb);\r\n\r\n\r\n\r\n    return foot;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n\r\n\r\n  function renderResults(){\r\n\r\n\r\n\r\n    resultsEl.innerHTML = \"\";\r\n\r\n\r\n\r\n    if (!state.selectedId) return;\r\n\r\n\r\n\r\n\r\n\r\n    var heading = document.createElement(\"p\");\r\n\r\n\r\n\r\n    heading.className = \"tbt-som-results-heading\";\r\n\r\n\r\n\r\n    var anyCard = false;\r\n\r\n\r\n\r\n\r\n\r\n    if (state.mode === \"comida\") {\r\n\r\n\r\n\r\n      var food = FOODS.filter(function(f){ return f.id === state.selectedId; })[0];\r\n\r\n\r\n\r\n      var rulesForFood = RULES[state.selectedId];\r\n\r\n\r\n\r\n      heading.textContent = \"Recommended styles for \" + food.label.toLowerCase();\r\n\r\n\r\n\r\n      resultsEl.appendChild(heading);\r\n\r\n\r\n\r\n      if (!rulesForFood) { resultsEl.appendChild(emptyState()); return; }\r\n\r\n\r\n\r\n\r\n\r\n      CATS.forEach(function(cat){\r\n\r\n\r\n\r\n        var rule = rulesForFood[cat];\r\n\r\n\r\n\r\n        var found = STYLES.filter(function(s){ return rule.test(s); }).slice(0, PER_CATEGORY);\r\n\r\n\r\n\r\n        found.forEach(function(s){\r\n\r\n\r\n\r\n          anyCard = true;\r\n\r\n\r\n\r\n          resultsEl.appendChild(cardForStyle(s, { cat:cat, text:rule.text(s) }));\r\n\r\n\r\n\r\n        });\r\n\r\n\r\n\r\n      });\r\n\r\n\r\n\r\n    } else {\r\n\r\n\r\n\r\n      var style = STYLES.filter(function(s){ return s.id === state.selectedId; })[0];\r\n\r\n\r\n\r\n      heading.textContent = style.label + \" (ABV \" + style.abv + \", IBU \" + style.ibu + \") pairs well with\";\r\n\r\n\r\n\r\n      resultsEl.appendChild(heading);\r\n\r\n\r\n\r\n\r\n\r\n      CATS.forEach(function(cat){\r\n\r\n\r\n\r\n        var found = FOODS.filter(function(f){\r\n\r\n\r\n\r\n          var rule = RULES[f.id] && RULES[f.id][cat];\r\n\r\n\r\n\r\n          return rule && rule.test(style);\r\n\r\n\r\n\r\n        }).slice(0, PER_CATEGORY);\r\n\r\n\r\n\r\n        found.forEach(function(f){\r\n\r\n\r\n\r\n          anyCard = true;\r\n\r\n\r\n\r\n          resultsEl.appendChild(cardForFood(f, { cat:cat, text:RULES[f.id][cat].text(style) }));\r\n\r\n\r\n\r\n        });\r\n\r\n\r\n\r\n      });\r\n\r\n\r\n\r\n    }\r\n\r\n\r\n\r\n\r\n\r\n    if (!anyCard) resultsEl.appendChild(emptyState());\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n\r\n\r\n  function emptyState(){\r\n\r\n\r\n\r\n    var p = document.createElement(\"p\");\r\n\r\n\r\n\r\n    p.className = \"tbt-som-empty\";\r\n\r\n\r\n\r\n    p.textContent = \"There is no rule loaded yet for this combination.\";\r\n\r\n\r\n\r\n    return p;\r\n\r\n\r\n\r\n  }\r\n\r\n\r\n\r\n\r\n\r\n  tabsEl.forEach(function(tab){\r\n\r\n\r\n\r\n    tab.addEventListener(\"click\", function(){\r\n\r\n\r\n\r\n      tabsEl.forEach(function(t){ t.classList.remove(\"is-active\"); t.setAttribute(\"aria-selected\",\"false\"); });\r\n\r\n\r\n\r\n      tab.classList.add(\"is-active\");\r\n\r\n\r\n\r\n      tab.setAttribute(\"aria-selected\",\"true\");\r\n\r\n\r\n\r\n      state.mode = tab.dataset.mode;\r\n\r\n\r\n\r\n      state.selectedId = null;\r\n\r\n\r\n\r\n      state.filter = \"\";\r\n\r\n\r\n\r\n      searchInput.value = \"\";\r\n\r\n\r\n\r\n      renderChips();\r\n\r\n\r\n\r\n      renderResults();\r\n\r\n\r\n\r\n    });\r\n\r\n\r\n\r\n  });\r\n\r\n\r\n\r\n\r\n\r\n  searchInput.addEventListener(\"input\", function(){\r\n\r\n\r\n\r\n    state.filter = searchInput.value.trim().toLowerCase();\r\n\r\n\r\n\r\n    renderChips();\r\n\r\n\r\n\r\n  });\r\n\r\n\r\n\r\n\r\n\r\n  renderChips();\r\n\r\n\r\n\r\n  renderResults();\r\n\r\n\r\n\r\n})();\r\n\r\n\r\n\r\n<\/script><\/p>\r\n<h2>Frequently Asked Questions (FAQ)<\/h2>\r\n<h3>1. How Does Beer Sommelier Work?<\/h3>\r\n<p>Beer Sommelier allows you to start from a dish or a beer and find recommended pairing combinations based on beer style and the principles of affinity, contrast, and complement.<\/p>\r\n<h3>2. What Principles Does Beer Sommelier Use to Recommend a Pairing?<\/h3>\r\n<p>Recommendations are based on three classic pairing principles: affinity, when similar characteristics are enhanced; contrast, when opposing characteristics are balanced; and complement, when beer and food integrate to create a balanced combination.<\/p>\r\n<h3>3. Can I Search for a Pairing Starting from a Dish?<\/h3>\r\n<p>Yes. You can select or search for a dish, and Beer Sommelier will show the beer styles that offer the most suitable combinations for that food.<\/p>\r\n<h3>4. Can I Search for Which Food Pairs with a Beer?<\/h3>\r\n<p>Yes. Select a beer or beer style to find out which foods best complement its characteristics.<\/p>\r\n<h3>5. Are Recommendations Based on Beer Styles?<\/h3>\r\n<p>Yes. Beer Sommelier uses currently recognized beer styles as a technical reference to establish pairing combinations.<\/p>\r\n<p><script type=\"application\/ld+json\">\r\n{\r\n  \"@context\": \"https:\/\/schema.org\",\r\n  \"@type\": \"FAQPage\",\r\n  \"mainEntity\": [\r\n    {\r\n      \"@type\": \"Question\",\r\n      \"name\": \"How Does Beer Sommelier Work?\",\r\n      \"acceptedAnswer\": {\r\n        \"@type\": \"Answer\",\r\n        \"text\": \"Beer Sommelier allows you to start from a dish or a beer and find recommended pairing combinations based on beer style and the principles of affinity, contrast, and complement.\"\r\n      }\r\n    },\r\n    {\r\n      \"@type\": \"Question\",\r\n      \"name\": \"What Principles Does Beer Sommelier Use to Recommend a Pairing?\",\r\n      \"acceptedAnswer\": {\r\n        \"@type\": \"Answer\",\r\n        \"text\": \"Recommendations are based on three classic pairing principles: affinity, when similar characteristics are enhanced; contrast, when opposing characteristics are balanced; and complement, when beer and food integrate to create a balanced combination.\"\r\n      }\r\n    },\r\n    {\r\n      \"@type\": \"Question\",\r\n      \"name\": \"Can I Search for a Pairing Starting from a Dish?\",\r\n      \"acceptedAnswer\": {\r\n        \"@type\": \"Answer\",\r\n        \"text\": \"Yes. You can select or search for a dish, and Beer Sommelier will show the beer styles that offer the most suitable combinations for that food.\"\r\n      }\r\n    },\r\n    {\r\n      \"@type\": \"Question\",\r\n      \"name\": \"Can I Search for Which Food Pairs with a Beer?\",\r\n      \"acceptedAnswer\": {\r\n        \"@type\": \"Answer\",\r\n        \"text\": \"Yes. Select a beer or beer style to find out which foods best complement its characteristics.\"\r\n      }\r\n    },\r\n    {\r\n      \"@type\": \"Question\",\r\n      \"name\": \"Are Recommendations Based on Beer Styles?\",\r\n      \"acceptedAnswer\": {\r\n        \"@type\": \"Answer\",\r\n        \"text\": \"Yes. Beer Sommelier uses currently recognized beer styles as a technical reference to establish pairing combinations.\"\r\n      }\r\n    }\r\n  ]\r\n}\r\n<\/script><\/p>\r\n","protected":false},"excerpt":{"rendered":"<p>Beer Sommelier is The Beer Times\u2122&#8217;s pairing tool. It recommends combinations between food and beer based on currently recognized beer styles and the three classic pairing principles: affinity, contrast, and complement. Choose whether you want to start from a dish or a beer, select an option from the list (or type to filter it), and<\/p>\n","protected":false},"author":1,"featured_media":49363,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"wpai_generated_summary":"","footnotes":""},"class_list":["post-49364","page","type-page","status-publish","has-post-thumbnail"],"_links":{"self":[{"href":"https:\/\/www.thebeertimes.com\/en\/wp-json\/wp\/v2\/pages\/49364","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.thebeertimes.com\/en\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.thebeertimes.com\/en\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.thebeertimes.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.thebeertimes.com\/en\/wp-json\/wp\/v2\/comments?post=49364"}],"version-history":[{"count":8,"href":"https:\/\/www.thebeertimes.com\/en\/wp-json\/wp\/v2\/pages\/49364\/revisions"}],"predecessor-version":[{"id":49391,"href":"https:\/\/www.thebeertimes.com\/en\/wp-json\/wp\/v2\/pages\/49364\/revisions\/49391"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.thebeertimes.com\/en\/wp-json\/wp\/v2\/media\/49363"}],"wp:attachment":[{"href":"https:\/\/www.thebeertimes.com\/en\/wp-json\/wp\/v2\/media?parent=49364"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}