(function attachMenuStore() {
  const DEFAULT_MENU_DATA = {
  "version": 1,
  "brand": {
    "eyebrow": "CARTA",
    "title": "CARTA",
    "description": ""
  },
  "defaultCategoryId": "tostadas",
  "categories": [
    {
      "id": "tostadas",
      "label": "Tostadas",
      "description": "Clásicas, saladas y dulces para empezar bien el día.",
      "items": [
        {
          "id": "clasica",
          "tag": "Tostadas",
          "name": "Clásica",
          "description": "Mantequilla & mermelada. Tomate & aceite.",
          "price": "3€",
          "badge": "",
          "image": "./assets/platos/clasica.webp",
          "alt": "Tostada Clásica",
          "featured": true
        },
        {
          "id": "delicia-serrana",
          "tag": "Tostadas",
          "name": "Delicia Serrana",
          "description": "Tomate & serrano.",
          "price": "4€",
          "badge": "",
          "image": "./assets/platos/delicia-serrana.webp",
          "alt": "Tostada Delicia Serrana",
          "featured": false
        },
        {
          "id": "serrana-verde",
          "tag": "Tostadas",
          "name": "Serrana Verde",
          "description": "Tomate, serrano & aguacate.",
          "price": "4,50€",
          "badge": "",
          "image": "./assets/platos/serrana-verde.webp",
          "alt": "Tostada Serrana Verde",
          "featured": false
        },
        {
          "id": "revoltosa",
          "tag": "Tostadas",
          "name": "Revoltosa",
          "description": "Tomate, serrano & huevo revuelto.",
          "price": "5,50€",
          "badge": "",
          "image": "./assets/platos/revoltosa.webp",
          "alt": "Tostada Revoltosa",
          "featured": false
        },
        {
          "id": "kinder-boom",
          "tag": "Tostadas",
          "name": "Kinder Boom",
          "description": "Crema de avellana, kinder & chocolate blanco.",
          "price": "5,00€",
          "badge": "",
          "image": "./assets/platos/kinder-boom.webp",
          "alt": "Tostada Kinder Boom",
          "featured": false
        },
        {
          "id": "doble-nutella",
          "tag": "Tostadas",
          "name": "Doble Nutella",
          "description": "Nutella, nutella blanca, fresas y plátano.",
          "price": "5€",
          "badge": "",
          "image": "./assets/platos/doble-nutella.webp",
          "alt": "Tostada Doble Nutella",
          "featured": false
        },
        {
          "id": "la-guaca-power",
          "tag": "Tostadas",
          "name": "La Guaca Power",
          "description": "Guacamole o aguacate, tomate cherry, huevo revuelto, rúcula & soja.",
          "price": "7€",
          "badge": "",
          "image": "./assets/platos/la-guaca-power.webp",
          "alt": "Tostada La Guaca Power",
          "featured": false
        }
      ]
    },
    {
      "id": "titas-dulce-salado",
      "label": "Dulce/Salado",
      "description": "Combinaciones dulces y saladas de la casa.",
      "items": [
        {
          "id": "banana-dark",
          "tag": "Dulce/Salado",
          "name": "Banana Dark",
          "description": "Crema de cacahuete, plátano & dark chocolat.",
          "price": "4,5€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Banana Dark",
          "featured": true
        },
        {
          "id": "guacamoleazo",
          "tag": "Dulce/Salado",
          "name": "Guacamoleazo",
          "description": "Guacamole, huevo revuelto & bacon.",
          "price": "6,50€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Guacamoleazo",
          "featured": false
        },
        {
          "id": "pavo-cremoso",
          "tag": "Dulce/Salado",
          "name": "Pavo Cremoso",
          "description": "Queso mascarpone, pavo & aguacate.",
          "price": "5€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Pavo Cremoso",
          "featured": false
        },
        {
          "id": "mascarpone-dorado",
          "tag": "Dulce/Salado",
          "name": "Mascarpone Dorado",
          "description": "Queso mascarpone, miel & nueces.",
          "price": "4,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Mascarpone Dorado",
          "featured": false
        },
        {
          "id": "mascarpone-berry",
          "tag": "Dulce/Salado",
          "name": "Mascarpone Berry",
          "description": "Queso mascarpone, fresas, arándanos & nueces.",
          "price": "5€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Mascarpone Berry",
          "featured": false
        },
        {
          "id": "salmon-green",
          "tag": "Dulce/Salado",
          "name": "Salmon Green",
          "description": "Base de tomate, aguacate, salmón ahumado, rúcula, huevo poché & salsa holandesa.",
          "price": "7€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Salmon Green",
          "featured": false
        },
        {
          "id": "morning-power",
          "tag": "Dulce/Salado",
          "name": "Morning Power",
          "description": "Huevos fritos o revueltos, beicon & salchichas.",
          "price": "Consultar",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Morning Power",
          "featured": false
        }
      ]
    },
    {
      "id": "extras",
      "label": "Extras",
      "description": "Añade lo que quieras.",
      "items": [
        {
          "id": "pan-sin-gluten",
          "tag": "Extra",
          "name": "Pan sin glúten",
          "description": "Suplemento.",
          "price": "1€",
          "badge": "Añadido",
          "image": "./assets/burger-plate.webp",
          "alt": "Extra pan sin gluten",
          "featured": false
        },
        {
          "id": "sirope",
          "tag": "Extra",
          "name": "Sirope",
          "description": "Suplemento.",
          "price": "0,50€",
          "badge": "Añadido",
          "image": "./assets/milkshake.webp",
          "alt": "Extra sirope",
          "featured": false
        },
        {
          "id": "fruta",
          "tag": "Extra",
          "name": "Fruta",
          "description": "Suplemento.",
          "price": "1€",
          "badge": "Añadido",
          "image": "./assets/milkshake.webp",
          "alt": "Extra fruta",
          "featured": false
        },
        {
          "id": "helado",
          "tag": "Extra",
          "name": "Helado",
          "description": "Suplemento.",
          "price": "2€",
          "badge": "Añadido",
          "image": "./assets/milkshake.webp",
          "alt": "Extra helado",
          "featured": false
        }
      ]
    },
    {
      "id": "bowls",
      "label": "Bowls",
      "description": "Bowls con base de yogur griego y toppings variados.",
      "items": [
        {
          "id": "tropical-greek",
          "tag": "Bowls",
          "name": "Tropical Greek",
          "description": "Yogur griego acompañado de moras, kiwi, mango, nueces & miel.",
          "price": "6€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Tropical Greek",
          "featured": true
        },
        {
          "id": "delicia-griega",
          "tag": "Bowls",
          "name": "Delicia Griega",
          "description": "Yogur griego acompañado de oreo, príncipe & nutella.",
          "price": "6€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Delicia Griega",
          "featured": false
        },
        {
          "id": "chocobueno",
          "tag": "Bowls",
          "name": "Chocobueno",
          "description": "Yogur griego acompañado de crema de avellana & kinder bueno.",
          "price": "5,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Chocobueno",
          "featured": false
        },
        {
          "id": "fruit-lover",
          "tag": "Bowls",
          "name": "Fruit Lover",
          "description": "Yogur griego acompañado de kiwi, fresas, plátano & naranja. Disponible sin base de yogur.",
          "price": "6,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Fruit Lover",
          "featured": false
        },
        {
          "id": "acai-bowl",
          "tag": "Bowls",
          "name": "Açai Bowl",
          "description": "Yogur griego, açai acompañado de fresas, plátano, muesli & chia.",
          "price": "7€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Acai Bowl",
          "featured": false
        }
      ]
    },
    {
      "id": "bagels",
      "label": "Bagels",
      "description": "Bagels y croasandwiches con opciones saladas y dulces.",
      "items": [
        {
          "id": "delicia-fresca",
          "tag": "Bagels",
          "name": "Delicia Fresca",
          "description": "Queso crema, pavo & aguacate.",
          "price": "5,50€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Delicia Fresca",
          "featured": true
        },
        {
          "id": "matutino",
          "tag": "Bagels",
          "name": "Matutino",
          "description": "Queso crema, huevo revuelto & bacón.",
          "price": "6€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Matutino",
          "featured": false
        },
        {
          "id": "crudo-fresco",
          "tag": "Bagels",
          "name": "Crudo & Fresco",
          "description": "Tomate, serrano, aguacate & chia.",
          "price": "5,50€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Crudo y Fresco",
          "featured": false
        },
        {
          "id": "iberian-twist",
          "tag": "Bagels",
          "name": "Iberian Twist",
          "description": "Tomate, huevo revuelto & serrano.",
          "price": "6€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Iberian Twist",
          "featured": false
        },
        {
          "id": "croasandwich-mixto",
          "tag": "Bagels",
          "name": "Croasandwich Mixto",
          "description": "Disponible en pan.",
          "price": "3,50€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Croasandwich Mixto",
          "featured": false
        },
        {
          "id": "croasandwich-deluxe",
          "tag": "Bagels",
          "name": "Croasandwich Deluxe",
          "description": "Queso crema, aguacate, pavo & huevo revuelto.",
          "price": "6€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Croasandwich Deluxe",
          "featured": false
        },
        {
          "id": "noruego",
          "tag": "Bagels",
          "name": "Noruego",
          "description": "Queso crema, aguacate & salmón ahumado.",
          "price": "6€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Noruego",
          "featured": false
        },
        {
          "id": "trio-dulce",
          "tag": "Bagels",
          "name": "Trio Dulce",
          "description": "Nutella, nuez & plátano.",
          "price": "4,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Trio Dulce",
          "featured": false
        }
      ]
    },
    {
      "id": "batidos",
      "label": "Batidos",
      "description": "Batidos cremosos, golosos y con topping top: puro capricho en cada sorbo.",
      "items": [
        {
          "id": "oreo-shake",
          "tag": "Batidos",
          "name": "Oreo Shake",
          "description": "Batido de la casa.",
          "price": "5€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Oreo Shake",
          "featured": true
        },
        {
          "id": "sweet-vainilla",
          "tag": "Batidos",
          "name": "Sweet Vainilla",
          "description": "Batido de la casa.",
          "price": "5€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Sweet Vainilla",
          "featured": false
        },
        {
          "id": "kinder-dream-shake",
          "tag": "Batidos",
          "name": "Kinder Dream Shake",
          "description": "Batido de la casa.",
          "price": "5€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Kinder Dream Shake",
          "featured": false
        },
        {
          "id": "sweet-cream",
          "tag": "Batidos",
          "name": "Sweet Cream",
          "description": "Batido de la casa.",
          "price": "5€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Sweet Cream",
          "featured": false
        }
      ]
    },
    {
      "id": "smoothies",
      "label": "Smoothies",
      "description": "Smoothies frescos y frutales, ligeros y llenos de sabor para cualquier momento.",
      "items": [
        {
          "id": "fresabana",
          "tag": "Smoothies",
          "name": "Fresabana",
          "description": "Fresa & plátano.",
          "price": "5€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Fresabana",
          "featured": true
        },
        {
          "id": "energia-verde",
          "tag": "Smoothies",
          "name": "Energia Verde",
          "description": "Piña, brócoli, apio, plátano & espinacas.",
          "price": "5€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Energía Verde",
          "featured": false
        },
        {
          "id": "tropical-mix",
          "tag": "Smoothies",
          "name": "Tropical Mix",
          "description": "Piña, kiwi, melón & mango.",
          "price": "5€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Tropical Mix",
          "featured": false
        },
        {
          "id": "jungle-juice",
          "tag": "Smoothies",
          "name": "Jungle Juice",
          "description": "Fresa, açai, grosella & mango.",
          "price": "5€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Jungle Juice",
          "featured": false
        }
      ]
    },
    {
      "id": "dulces",
      "label": "Dulces",
      "description": "Bollería y croissants de la carta.",
      "items": [
        {
          "id": "nutella-croissant",
          "tag": "Dulces",
          "name": "Nutella Croissant",
          "description": "Croissant relleno de nutella.",
          "price": "3,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Nutella Croissant",
          "featured": false
        },
        {
          "id": "pistacho-dream-croissant",
          "tag": "Dulces",
          "name": "Pistacho Dream Croissant",
          "description": "Croissant con crema de pistacho.",
          "price": "3,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Pistacho Dream Croissant",
          "featured": false
        },
        {
          "id": "croissant-tentacion-kinder",
          "tag": "Dulces",
          "name": "Croissant Tentación Kinder",
          "description": "Croissant con relleno de kinder.",
          "price": "3,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Croissant Tentación Kinder",
          "featured": false
        },
        {
          "id": "bolleria-surtida",
          "tag": "Dulces",
          "name": "Bolleria Surtida",
          "description": "Pregunta a nuestro personal.",
          "price": "2€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Bolleria Surtida",
          "featured": false
        },
        {
          "id": "croissant-sweet-fruit-nutella",
          "tag": "Dulces",
          "name": "Croissant Sweet Fruit & Nutella",
          "description": "Relleno de nutella, plátano, fresas, arándanos & kiwi.",
          "price": "4,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Croissant Sweet Fruit y Nutella",
          "featured": true
        }
      ]
    },
    {
      "id": "cafes",
      "label": "Cafés",
      "description": "Cafetería y bebidas calientes.",
      "items": [
        {
          "id": "capuchino",
          "tag": "Cafés",
          "name": "Capuchino",
          "description": "Café capuchino.",
          "price": "2,20€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Capuchino",
          "featured": true
        },
        {
          "id": "bombon",
          "tag": "Cafés",
          "name": "Bombón",
          "description": "Café bombón.",
          "price": "Consultar",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Bombón",
          "featured": false
        },
        {
          "id": "carajillo",
          "tag": "Cafés",
          "name": "Carajillo",
          "description": "Café carajillo.",
          "price": "3,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Carajillo",
          "featured": false
        },
        {
          "id": "matcha-latte",
          "tag": "Cafés",
          "name": "Matcha Latte",
          "description": "Bebida matcha.",
          "price": "2,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Matcha Latte",
          "featured": false
        },
        {
          "id": "chai-latte",
          "tag": "Cafés",
          "name": "Chai Latte",
          "description": "Bebida chai.",
          "price": "Consultar",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Chai Latte",
          "featured": false
        },
        {
          "id": "chocolate",
          "tag": "Cafés",
          "name": "Chocolate",
          "description": "Chocolate caliente.",
          "price": "Consultar",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Chocolate caliente",
          "featured": false
        }
      ]
    },
    {
      "id": "tortitas-gofres",
      "label": "Tortitas & Gofres",
      "description": "Opciones dulces y saladas para elegir entre tortitas o gofres.",
      "items": [
        {
          "id": "delicia-de-nutella",
          "tag": "Tortitas & Gofres",
          "name": "Delicia de Nutella",
          "description": "Escoge entre cualquiera de las dos opciones y disfruta del sabor a nutella.",
          "price": "4€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Delicia de Nutella",
          "featured": true
        },
        {
          "id": "capricho-dulce",
          "tag": "Tortitas & Gofres",
          "name": "Capricho Dulce",
          "description": "Nutella, oreo & nata.",
          "price": "4,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Capricho Dulce",
          "featured": false
        },
        {
          "id": "el-antojo",
          "tag": "Tortitas & Gofres",
          "name": "El Antojo",
          "description": "Nutella, kinder & kitkat.",
          "price": "4€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "El Antojo",
          "featured": false
        },
        {
          "id": "buenorro",
          "tag": "Tortitas & Gofres",
          "name": "Buenorro",
          "description": "Crema de avellanas & kinder.",
          "price": "4€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Buenorro",
          "featured": false
        },
        {
          "id": "capricho-principe",
          "tag": "Tortitas & Gofres",
          "name": "Capricho Principe",
          "description": "Crema de avellanas, nata & principe.",
          "price": "5€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Capricho Principe",
          "featured": false
        },
        {
          "id": "tentacion-blanca",
          "tag": "Tortitas & Gofres",
          "name": "Tentacion Blanca",
          "description": "Crema de avellanas, chocolate blanco & filipinos.",
          "price": "4,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Tentación Blanca",
          "featured": false
        },
        {
          "id": "capricho-natural",
          "tag": "Tortitas & Gofres",
          "name": "Capricho Natural",
          "description": "Fresas, arándanos, plátano, nueces & miel.",
          "price": "5,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Capricho Natural",
          "featured": false
        },
        {
          "id": "tentacion-lotus",
          "tag": "Tortitas & Gofres",
          "name": "Tentación Lotus",
          "description": "Crema lotus, chocolate blanco & galletas lotus.",
          "price": "4,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Tentación Lotus",
          "featured": false
        },
        {
          "id": "dino-lovers",
          "tag": "Tortitas & Gofres",
          "name": "Dino Lovers",
          "description": "Nutella, crema de pistachos, galleta dino, helado de vainilla & pistachos.",
          "price": "7€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Dino Lovers",
          "featured": false
        },
        {
          "id": "berrylicious",
          "tag": "Tortitas & Gofres",
          "name": "Berrylicious",
          "description": "Nutella, fresas, galleta de oreo & helado de oreo.",
          "price": "7€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Berrylicious",
          "featured": false
        },
        {
          "id": "blanco-total",
          "tag": "Tortitas & Gofres",
          "name": "Blanco Total",
          "description": "Nocilla blanca, filipinos & helado de nata.",
          "price": "6€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Blanco Total",
          "featured": false
        },
        {
          "id": "morning-deluxe",
          "tag": "Tortitas & Gofres",
          "name": "Morning Deluxe",
          "description": "Base de tomate, beicon, huevo poché con salsa holandesa.",
          "price": "7€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Morning Deluxe",
          "featured": false
        },
        {
          "id": "golden-cream",
          "tag": "Tortitas & Gofres",
          "name": "Golden Cream",
          "description": "Queso mascarpone, miel & almendras laminadas.",
          "price": "4,50€",
          "badge": "",
          "image": "./assets/milkshake.webp",
          "alt": "Golden Cream",
          "featured": false
        },
        {
          "id": "combo-para-llevar",
          "tag": "Tortitas & Gofres",
          "name": "Crea tu combo para llevar",
          "description": "Mini tortitas o gofres + 2 toppins a elegir entre fruta o chocolate. Cada topping a mayores +0,50€.",
          "price": "5€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Combo para llevar",
          "featured": false
        }
      ]
    },
    {
      "id": "entrantes",
      "label": "Entrantes",
      "description": "Para compartir o abrir apetito.",
      "items": [
        {
          "id": "patatas",
          "tag": "Entrantes",
          "name": "Patatas",
          "description": "Clásicas, crujientes & perfectas para compartir.",
          "price": "3€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Patatas",
          "featured": false
        },
        {
          "id": "patatas-chemosas-cheddar",
          "tag": "Entrantes",
          "name": "Patatas Chemosas de Cheddar",
          "description": "Patatas crujientes bañadas en salsa cheddar & coronadas con bacon bits.",
          "price": "5,5€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Patatas chemosas de cheddar",
          "featured": true
        },
        {
          "id": "patatas-trufadas",
          "tag": "Entrantes",
          "name": "Patatas Trufadas",
          "description": "Patatas crujientes con polvo de parmesano, mayonesa trufada & cebollino fresco.",
          "price": "6€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Patatas trufadas",
          "featured": false
        },
        {
          "id": "alitas-kentucky",
          "tag": "Entrantes",
          "name": "Alitas Kentucky",
          "description": "Alitas o muslos jugosos con cobertura kentucky (8 und).",
          "price": "12€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Alitas kentucky",
          "featured": false
        },
        {
          "id": "solomillo-pollo-kentucky",
          "tag": "Entrantes",
          "name": "Solomillo de Pollo Kentucky",
          "description": "Crujientes por fuera, jugosos por dentro, acompañados de salsa cheddar.",
          "price": "12€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Solomillo de pollo kentucky",
          "featured": false
        },
        {
          "id": "cheese-bites",
          "tag": "Entrantes",
          "name": "Cheese Bites",
          "description": "Mezcla deliciosa entre queso & pimientos empanados.",
          "price": "8€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Cheese Bites",
          "featured": false
        },
        {
          "id": "crujiente-del-mar",
          "tag": "Entrantes",
          "name": "Crujiente del Mar",
          "description": "Colas de langostinos crujientes acompañadas de salsa alioli.",
          "price": "12€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Crujiente del mar",
          "featured": false
        },
        {
          "id": "perlas-de-centolla",
          "tag": "Entrantes",
          "name": "Perlas de Centolla",
          "description": "Croquetas crujientes rellenas de una deliciosa centolla.",
          "price": "10€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Perlas de centolla",
          "featured": false
        },
        {
          "id": "bocados-del-cantabrico",
          "tag": "Entrantes",
          "name": "Bocados del Cantábrico",
          "description": "Croquetas crujientes rellenas de chipirones en tinta.",
          "price": "10€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Bocados del Cantábrico",
          "featured": false
        }
      ]
    },
    {
      "id": "ensaladas",
      "label": "Ensaladas",
      "description": "Opciones frescas y completas.",
      "items": [
        {
          "id": "tradicional",
          "tag": "Ensaladas",
          "name": "Tradicional",
          "description": "Lechuga, tomate & cebolla.",
          "price": "5€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Ensalada tradicional",
          "featured": false
        },
        {
          "id": "huerta-mar",
          "tag": "Ensaladas",
          "name": "Huerta & Mar",
          "description": "Lechuga, tomate, cebolla crujiente, atún, huevo & palitos de cangrejo.",
          "price": "9€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Ensalada huerta y mar",
          "featured": true
        },
        {
          "id": "crunchy-salad",
          "tag": "Ensaladas",
          "name": "Crunchy Salad",
          "description": "Lechuga, tomate, cebolla crujiente, beicon bits & frutos secos.",
          "price": "Consultar",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Crunchy salad",
          "featured": false
        }
      ]
    },
    {
      "id": "burgers",
      "label": "Burgers",
      "description": "Todas las hamburguesas van acompañadas de patatas. Por 2€ más, hazla completa.",
      "items": [
        {
          "id": "sabrosa",
          "tag": "Burgers",
          "name": "Sabrosa",
          "description": "Carne de ternera, queso cheddar, aros de cebolla, beicon bits & mucho queso para chuparse los dedos.",
          "price": "Consultar",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Burger Sabrosa",
          "featured": false
        },
        {
          "id": "deliciosa",
          "tag": "Burgers",
          "name": "Deliciosa",
          "description": "Carne de ternera, queso cheddar & pulled pork a la barbacoa.",
          "price": "12€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Burger Deliciosa",
          "featured": true
        },
        {
          "id": "hambrienta",
          "tag": "Burgers",
          "name": "Hambrienta",
          "description": "Carne de pollo, queso cheedar, cebolla crujientes, beicon bits & barbacoa.",
          "price": "10€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Burger Hambrienta",
          "featured": false
        },
        {
          "id": "exquisita",
          "tag": "Burgers",
          "name": "Exquisita",
          "description": "Carne de vaca vieja, queso edam, cebolla caramelizada, tomate asado, brotes frescos & beicon bits.",
          "price": "12,50€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Burger Exquisita",
          "featured": false
        },
        {
          "id": "riquisima",
          "tag": "Burgers",
          "name": "Riquisima",
          "description": "Carne de ternera, rulo de cabra, cebolla caramelizada, brotes frescos & salsa ajo negro.",
          "price": "11€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Burger Riquisima",
          "featured": false
        },
        {
          "id": "clasica-burger",
          "tag": "Burgers",
          "name": "Clásica",
          "description": "Carne de ternera o pollo & queso.",
          "price": "7€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Burger Clásica",
          "featured": false
        },
        {
          "id": "octoburger",
          "tag": "Burgers",
          "name": "Octoburger",
          "description": "Pulpo a feira con queso san simòn.",
          "price": "15€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Octoburger",
          "featured": false
        },
        {
          "id": "la-intensa",
          "tag": "Burgers",
          "name": "La Intensa",
          "description": "Zorza de cerdo con queso edam.",
          "price": "11€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Burger La Intensa",
          "featured": false
        }
      ]
    },
    {
      "id": "sandwich",
      "label": "Sandwich",
      "description": "Todos van acompañados de patatas.",
      "items": [
        {
          "id": "brioche-chiken",
          "tag": "Sandwich",
          "name": "Brioche Chiken",
          "description": "Pollo rebozado al estilo kentucky, salsa koreana con toque picante, ensalada de col & homemade pickles.",
          "price": "10€",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Brioche Chiken",
          "featured": true
        },
        {
          "id": "brioche-pulled-pork",
          "tag": "Sandwich",
          "name": "Brioche Pulled Pork",
          "description": "Cerdo desmenuzado, BBQ ahumada & col morada.",
          "price": "Consultar",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Brioche Pulled Pork",
          "featured": false
        },
        {
          "id": "brioche-trufado",
          "tag": "Sandwich",
          "name": "Brioche Trufado",
          "description": "Revuelto campero, champiñones laminados, queso parmesamo & salsa trufada.",
          "price": "Consultar",
          "badge": "",
          "image": "./assets/burger-plate.webp",
          "alt": "Brioche Trufado",
          "featured": false
        }
      ]
    }
  ]
};

  const clone = (value) => JSON.parse(JSON.stringify(value));

  const safeText = (value, fallback) => {
    if (typeof value !== "string") {
      return fallback;
    }
    const trimmed = value.trim();
    return trimmed.length ? trimmed : fallback;
  };

  const normalizeItem = (item, fallbackItem) => ({
    id: safeText(item?.id, fallbackItem.id),
    tag: safeText(item?.tag, fallbackItem.tag),
    name: safeText(item?.name, fallbackItem.name),
    description: safeText(item?.description, fallbackItem.description),
    price: safeText(item?.price, fallbackItem.price),
    badge: safeText(item?.badge, fallbackItem.badge),
    image: safeText(item?.image, fallbackItem.image),
    alt: safeText(item?.alt, fallbackItem.alt),
    featured: Boolean(item?.featured),
    essential: Boolean(item?.essential)
  });

  const normalizeCategory = (category, fallbackCategory) => {
    const sourceItems = Array.isArray(category?.items) ? category.items : [];
    const fallbackItems = Array.isArray(fallbackCategory.items) ? fallbackCategory.items : [];
    const normalizedItems = sourceItems.length
      ? sourceItems.map((entry, index) => normalizeItem(entry, fallbackItems[index] || fallbackItems[0]))
      : fallbackItems.map((entry) => normalizeItem(entry, entry));

    return {
      id: safeText(category?.id, fallbackCategory.id),
      label: safeText(category?.label, fallbackCategory.label),
      description: safeText(category?.description, fallbackCategory.description),
      items: normalizedItems
    };
  };

  const normalizeData = (candidate) => {
    const fallback = DEFAULT_MENU_DATA;
    const source = candidate && typeof candidate === "object" ? candidate : {};
    const sourceCategories = Array.isArray(source.categories) ? source.categories : [];

    const categories = fallback.categories.map((fallbackCategory) => {
      const match = sourceCategories.find((entry) => entry?.id === fallbackCategory.id);
      if (match) {
        return normalizeCategory(match, fallbackCategory);
      }
      return normalizeCategory(fallbackCategory, fallbackCategory);
    });

    const defaultCategoryId = safeText(source.defaultCategoryId, fallback.defaultCategoryId);
    const hasDefault = categories.some((entry) => entry.id === defaultCategoryId);

    return {
      version: 1,
      brand: {
        eyebrow: safeText(source.brand?.eyebrow, fallback.brand.eyebrow),
        title: safeText(source.brand?.title, fallback.brand.title),
        description: safeText(source.brand?.description, fallback.brand.description)
      },
      defaultCategoryId: hasDefault ? defaultCategoryId : categories[0].id,
      categories
    };
  };

  let cachedData = null;

  const MENU_READ_SOURCES = ["./menu-data.json", "./api/menu.php", "./api/menu"];
  const MENU_WRITE_TARGETS = ["./api/menu.php", "./api/menu"];
  const IMAGE_UPLOAD_TARGETS = ["./api/upload.php", "./api/upload"];

  const parseJSON = async (response) => {
    const text = await response.text();
    if (!text.trim()) {
      return null;
    }
    return JSON.parse(text);
  };

  const getResponseErrorText = async (response, fallbackMessage) => {
    try {
      const text = await response.text();
      if (!text.trim()) {
        return fallbackMessage;
      }

      try {
        const parsed = JSON.parse(text);
        if (parsed && typeof parsed === "object") {
          if (typeof parsed.error === "string" && parsed.error.trim()) {
            return parsed.error.trim();
          }
          if (typeof parsed.message === "string" && parsed.message.trim()) {
            return parsed.message.trim();
          }
        }
      } catch (jsonError) {
        // keep raw response text as fallback
      }

      return text.trim();
    } catch (readError) {
      return fallbackMessage;
    }
  };

  const fetchMenuData = async () => {
    for (const source of MENU_READ_SOURCES) {
      try {
        const response = await fetch(source, { cache: "no-store" });
        if (!response.ok) {
          continue;
        }
        const parsed = await parseJSON(response);
        if (!parsed) {
          continue;
        }
        return normalizeData(parsed);
      } catch (error) {
        continue;
      }
    }

    return clone(DEFAULT_MENU_DATA);
  };

  const saveMenuDataToFile = async (normalizedData) => {
    let lastError = null;
    for (const target of MENU_WRITE_TARGETS) {
      try {
        const response = await fetch(target, {
          method: "POST",
          headers: {
            "Content-Type": "application/json"
          },
          body: JSON.stringify(normalizedData)
        });

        if (!response.ok) {
          const reason = await getResponseErrorText(response, "No se pudo guardar en archivo.");
          lastError = new Error(`${reason} (endpoint: ${target})`);
          continue;
        }

        return;
      } catch (error) {
        const detail =
          error instanceof Error && error.message ? ` ${error.message}` : "";
        lastError = new Error(`No se pudo conectar con ${target}.${detail}`.trim());
      }
    }

    throw (
      lastError ||
      new Error(
        `No se pudo guardar en archivo. Endpoints probados: ${MENU_WRITE_TARGETS.join(", ")}`
      )
    );
  };

  const uploadImageToServer = async (file, itemId = "item") => {
    let lastError = null;

    for (const target of IMAGE_UPLOAD_TARGETS) {
      try {
        const payload = new FormData();
        payload.append("image", file);
        payload.append("itemId", itemId);

        const response = await fetch(target, {
          method: "POST",
          body: payload
        });

        if (!response.ok) {
          const reason = await getResponseErrorText(response, "No se pudo subir imagen.");
          lastError = new Error(`${reason} (endpoint: ${target})`);
          continue;
        }

        const json = await response.json();
        if (!json.path) {
          lastError = new Error("Respuesta de subida inválida.");
          continue;
        }

        return json;
      } catch (error) {
        const detail =
          error instanceof Error && error.message ? ` ${error.message}` : "";
        lastError = new Error(`No se pudo conectar con ${target}.${detail}`.trim());
      }
    }

    throw (
      lastError ||
      new Error(
        `No se pudo subir imagen. Endpoints probados: ${IMAGE_UPLOAD_TARGETS.join(", ")}`
      )
    );
  };

  const MenuStore = {
    getDefaultData() {
      return clone(DEFAULT_MENU_DATA);
    },
    normalizeData,
    async loadData({ force = false } = {}) {
      if (!force && cachedData) {
        return clone(cachedData);
      }
      cachedData = await fetchMenuData();
      return clone(cachedData);
    },
    async saveData(data) {
      const normalized = normalizeData(data);
      await saveMenuDataToFile(normalized);
      cachedData = normalized;
      return clone(normalized);
    },
    async resetData() {
      const resetData = clone(DEFAULT_MENU_DATA);
      await saveMenuDataToFile(resetData);
      cachedData = resetData;
      return clone(resetData);
    },
    async uploadImage(file, itemId) {
      return uploadImageToServer(file, itemId);
    }
  };

  window.MenuStore = MenuStore;
})();
