{"id":2245,"date":"2026-02-12T12:32:03","date_gmt":"2026-02-12T11:32:03","guid":{"rendered":"https:\/\/sansebastiancookingclasses.com\/proximas-clases\/"},"modified":"2026-02-27T08:50:33","modified_gmt":"2026-02-27T07:50:33","slug":"proximas-clases","status":"publish","type":"page","link":"https:\/\/sansebastiancookingclasses.com\/es\/proximas-clases\/","title":{"rendered":"Pr\u00f3ximas clases"},"content":{"rendered":"\n<!-- CALENDARIO MIMO \u00b7 UI con filtro de categor\u00eda y resultados \"solo letra\" (t\u00edtulo enlazado + meta inline + CTA) -->\n<style>\n  \/* ====== CALENDARIO ====== *\/\n  .calendar-container { font-family:'Chapeau','Source Code Pro',Arial,sans-serif; max-width:980px; margin:0 auto; background:#fff; padding:20px; border-radius:14px; box-shadow:0 4px 14px rgba(0,0,0,.08); }\n  .calendar-header { display:flex; align-items:center; justify-content:space-between; gap:10px; margin-bottom:12px; }\n  .calendar-header h2 { margin:0; font-size:22px; letter-spacing:.2px; }\n  .calendar-header .nav { display:flex; gap:8px; }\n  .calendar-header button, .calendar-actions button { background:#000; color:#fff; border:0; border-radius:10px; padding:10px 14px; cursor:pointer; font-family:inherit; }\n  .calendar-header button:hover, .calendar-actions button:hover { opacity:.85; }\n  .calendar { display:grid; grid-template-columns:repeat(7,1fr); border:1px solid #e5e5e5; border-radius:10px; overflow:hidden; }\n  .day-header { padding:10px; text-align:center; background:#fafafa; border-bottom:1px solid #eee; font-weight:600; }\n  .day { border-right:1px solid #f0f0f0; border-bottom:1px solid #f0f0f0; min-height:64px; padding:10px; text-align:center; cursor:pointer; user-select:none; }\n  .day:nth-child(7n) { border-right:0; }\n  .day:hover { background:#f6f6f6; }\n  .day.past { color:#aaa; cursor:not-allowed; background:#fbfbfb; }\n  .day.today { background:#c49b00; color:#fff; font-weight:700; }\n  .day.selected { outline:2px solid #000; outline-offset:-2px; background:#111; color:#fff; }\n  .calendar-actions { display:flex; flex-wrap:wrap; gap:8px; margin-top:12px; align-items:center; }\n  .calendar-actions .secondary { background:#f1f1f1; color:#111; }\n  .calendar-actions .ghost { background:transparent; color:#111; border:1px solid #ddd; }\n  .calendar-actions .pill { border-radius:999px; padding-inline:16px; }\n  .selection-count { margin-left:auto; color:#444; font-size:14px; }\n\n  \/* ====== RESULTADOS (solo letra) ====== *\/\n  #mimo-results { margin-top:22px; display:grid; gap:20px; }\n  .mimo-day-block { background:#fafafa; border:1px solid #eee; border-radius:12px; padding:16px; }\n  .mimo-day-title { margin:0 0 10px; font-size:18px; border-left:4px solid #000; padding-left:10px; }\n  .mimo-loading { font-size:14px; color:#555; }\n  .mimo-iframe { width:100%; border:0; border-radius:8px; display:block; }\n  .mimo-toolbar { display:flex; gap:12px; align-items:center; margin-top:10px; }\n  .mimo-link { font-size:13px; }\n\n  \/* \u2014\u2014\u2014 Estilos del listado \"solo letra\" (aplican a shadow host y fallback) \u2014\u2014\u2014 *\/\n  .mimo-textonly ul.products { display:block !important; padding:0 !important; margin:0 !important; }\n  .mimo-textonly ul.products li.product {\n    list-style:none !important; border:1px solid #e6e6e6 !important; border-radius:10px !important; background:#fff !important;\n    padding:16px !important; display:block !important; position:relative !important; min-height:96px !important; margin:0 0 26px 0 !important;\n    width:100% !important; float:none !important; clear:both !important;\n  }\n  .mimo-textonly ul.products li.product img,\n  .mimo-textonly ul.products li.product picture,\n  .mimo-textonly ul.products li.product figure,\n  .mimo-textonly ul.products li.product .product-loop-thumb,\n  .mimo-textonly ul.products li.product .product-thumbnail,\n  .mimo-textonly ul.products li.product .mk-product-image { display:none !important; }\n\n  .mimo-textonly .m-head { display:flex; gap:12px; align-items:center; justify-content:space-between; flex-wrap:wrap; }\n  .mimo-textonly .m-title-meta { display:flex; align-items:baseline; gap:10px; flex:1 1 auto; min-width:240px; }\n  .mimo-textonly .m-title-meta .woocommerce-loop-product__title,\n  .mimo-textonly .m-title-meta .product-title,\n  .mimo-textonly .m-title-meta h2, .mimo-textonly .m-title-meta h3, .mimo-textonly .m-title-meta h4 { margin:0; font-size:18px; line-height:1.25; font-weight:700; color:#2a2a2a; }\n  .mimo-textonly .m-title-meta a,\n  .mimo-textonly .m-title-meta a:visited,\n  .mimo-textonly .m-title-meta a:hover,\n  .mimo-textonly .m-title-meta a:focus { color:#2a2a2a !important; text-decoration:none !important; outline:0 !important; }\n  .mimo-textonly .m-meta-inline { color:#555; font-size:14px; margin:0; white-space:wrap; }\n  .mimo-textonly .m-cta { display:inline-flex; align-items:center; justify-content:center; gap:8px; padding:8px 12px; border-radius:999px; border:1px solid #333; background:transparent; color:#333 !important; text-decoration:none !important; font-size:13px; line-height:1; font-weight:600; white-space:nowrap; }\n  .mimo-textonly .m-cta:hover { background:#111; color:#fff !important; border-color:#111; }\n\n  @media (max-width:768px){\n    .calendar-container { padding:12px; box-shadow:none; border:1px solid #eee; }\n    .calendar-header h2 { font-size:18px; }\n    .day, .day-header { padding:8px; font-size:13px; }\n    .mimo-textonly .m-head{ flex-direction:column; align-items:flex-start; }\n    .mimo-textonly .m-cta{ width:100%; }\n  }\n<\/style>\n\n<div class=\"calendar-container\" id=\"calendarContainer\">\n  <div class=\"calendar-header\">\n    <div class=\"nav\">\n      <button id=\"prevMonth\" aria-label=\"Previous month\">\u00ab Previous<\/button>\n      <button id=\"nextMonth\" aria-label=\"Next month\">Next \u00bb<\/button>\n    <\/div>\n    <h2 id=\"monthYear\"><\/h2>\n  <\/div>\n\n  <div class=\"calendar\" id=\"calendar\"><\/div>\n\n  <div class=\"calendar-actions\">\n    <label class=\"pill\" title=\"Filter by category\" style=\"border:1px solid #ddd;\">\n      <select id=\"categoryFilter\" style=\"border:0;background:transparent;font-family:inherit;\">\n        <option value=\"\">All categories<\/option>\n        <option value=\"cooking-classes\">Cooking classes<\/option>\n        <option value=\"food-tours\">Food tours<\/option>\n      <\/select>\n    <\/label>\n    <button id=\"btnThisWeek\" class=\"secondary pill\" type=\"button\">This week<\/button>\n    <button id=\"btnClear\" class=\"ghost pill\" type=\"button\">Clear selection<\/button>\n    <span class=\"selection-count\" id=\"selCount\">0 selected<\/span>\n    <button id=\"btnShow\" class=\"pill\" type=\"button\">Show availability<\/button>\n    <button id=\"btnClearResults\" class=\"ghost pill\" type=\"button\" style=\"display:none;\">Clear results<\/button>\n  <\/div>\n\n  <div id=\"mimo-results\" class=\"mimo-textonly\"><\/div>\n<\/div>\n\n<script>\nwindow.addEventListener('DOMContentLoaded', function () {\n  (function(){\n    \/* === CONFIG === *\/\n    const SEARCH_SLUG = \"https:\/\/sansebastiancookingclasses.com\/search-availability\";\n\n    const el = {\n      calendar: document.getElementById('calendar'),\n      monthYear: document.getElementById('monthYear'),\n      prev: document.getElementById('prevMonth'),\n      next: document.getElementById('nextMonth'),\n      btnWeek: document.getElementById('btnThisWeek'),\n      btnClear: document.getElementById('btnClear'),\n      btnShow: document.getElementById('btnShow'),\n      selCount: document.getElementById('selCount'),\n      btnClearResults: document.getElementById('btnClearResults'),\n      results: document.getElementById('mimo-results'),\n      category: document.getElementById('categoryFilter'),\n    };\n\n    \/* \u2705 Guardas: si WP ejecuta raro o falta algo, no revienta *\/\n    if (!el.calendar || !el.monthYear || !el.prev || !el.next) return;\n\n    let view = new Date(); view.setDate(1);\n    let lastAnchor = null;\n    const selected = new Set();\n\n    const today = new Date(new Date().toLocaleString('en-US', { timeZone: 'Europe\/Madrid' }));\n    today.setHours(0,0,0,0);\n\n    const daysInWeek = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'];\n    const monthsInYear = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];\n\n    const ymd = (date) => {\n      const madrid = new Date(date.toLocaleString('en-US', { timeZone: 'Europe\/Madrid' }));\n      const y = madrid.getFullYear();\n      const m = String(madrid.getMonth() + 1).padStart(2, '0');\n      const d = String(madrid.getDate()).padStart(2, '0');\n      return `${y}-${m}-${d}`;\n    };\n\n    const parseYMD = (s)=> { const m=\/^(\\d{4})-(\\d{2})-(\\d{2})$\/.exec(s); return m?new Date(+m[1],+m[2]-1,+m[3]):null; };\n    const getDaysInMonth = (m,y)=> new Date(y, m+1, 0).getDate();\n    const isPast = (d)=> d < today;\n\n    function setSelected(dateStr, on=true){ on?selected.add(dateStr):selected.delete(dateStr); }\n    function updateCount(){ if(el.selCount) el.selCount.textContent = `${selected.size} selected`; }\n\n    function render(){\n      const month = view.getMonth(), year = view.getFullYear();\n      el.calendar.innerHTML='';\n      el.monthYear.textContent = `${monthsInYear[month]} ${year}`;\n\n      daysInWeek.forEach(d=>{ const h=document.createElement('div'); h.className='day-header'; h.textContent=d; el.calendar.appendChild(h); });\n\n      const firstDay = new Date(year, month, 1).getDay();\n      const mondayFirst = (firstDay === 0 ? 7 : firstDay);\n      for (let i=1; i<mondayFirst; i++){ const e=document.createElement('div'); e.className='day'; e.setAttribute('aria-hidden','true'); el.calendar.appendChild(e); }\n\n      const dim = getDaysInMonth(month, year);\n      for (let i=1; i<=dim; i++){\n        const d = new Date(year, month, i);\n        const dStr = ymd(d);\n        const cell = document.createElement('div'); cell.className='day'; cell.textContent=i;\n\n        if (isPast(d)) {\n          cell.classList.add('past');\n        } else {\n          cell.dataset.date = dStr;\n          if (selected.has(dStr)) cell.classList.add('selected');\n          if (d.getTime() === today.getTime()) cell.classList.add('today');\n\n          cell.addEventListener('click', (ev)=>{\n            if (ev.shiftKey && lastAnchor) {\n              const a = parseYMD(lastAnchor); const b = d;\n              let start=a, end=b; if (a>b) { start=b; end=a; }\n              for (let dt=new Date(start); dt<=end; dt.setDate(dt.getDate()+1)){\n                if (!isPast(dt)) setSelected(ymd(dt), true);\n              }\n            } else {\n              if (selected.has(dStr)) setSelected(dStr,false); else setSelected(dStr,true);\n              lastAnchor = dStr;\n            }\n            updateSelectionStyles();\n          });\n        }\n        el.calendar.appendChild(cell);\n      }\n\n      const cells = el.calendar.querySelectorAll('.day, .day-header').length;\n      const mod = cells % 7;\n      if (mod) for (let k=0;k<7-mod;k++){ const e=document.createElement('div'); e.className='day'; e.setAttribute('aria-hidden','true'); el.calendar.appendChild(e); }\n\n      updateCount();\n    }\n\n    function updateSelectionStyles(){\n      el.calendar.querySelectorAll('.day').forEach(cell=>{\n        const dStr = cell.dataset.date;\n        if (!dStr) return;\n        cell.classList.toggle('selected', selected.has(dStr));\n      });\n      updateCount();\n    }\n\n    el.prev.addEventListener('click', ()=>{ view.setMonth(view.getMonth()-1); render(); });\n    el.next.addEventListener('click', ()=>{ view.setMonth(view.getMonth()+1); render(); });\n\n    if (el.btnClear) el.btnClear.addEventListener('click', ()=>{ selected.clear(); updateSelectionStyles(); });\n\n    if (el.btnWeek) el.btnWeek.addEventListener('click', ()=>{\n      const baseStr = lastAnchor || ymd(today);\n      const base = parseYMD(baseStr);\n      const dow = (base.getDay() || 7);\n      const monday = new Date(base); monday.setDate(base.getDate() - (dow-1));\n      for (let i=0;i<7;i++){\n        const dt=new Date(monday); dt.setDate(monday.getDate()+i);\n        if(!isPast(dt)) setSelected(ymd(dt), true);\n      }\n      updateSelectionStyles();\n    });\n\n    function prettyDate(ymdStr) {\n      const parts = (ymdStr || '').split('-').map(Number);\n      if (parts.length !== 3 || parts.some(n=>!n)) return ymdStr;\n      const [Y, M, D] = parts;\n      const utcNoon = new Date(Date.UTC(Y, M - 1, D, 12, 0, 0));\n      return new Intl.DateTimeFormat('en-GB', {\n        weekday: 'long',\n        year: 'numeric',\n        month: 'long',\n        day: 'numeric',\n        timeZone: 'Europe\/Madrid'\n      }).format(utcNoon);\n    }\n\n    const removeMiniatures = (root)=>{\n      root.querySelectorAll('img, picture, figure, .product-loop-thumb, .product-thumbnail, .mk-product-image')\n        .forEach(elm=>{ try{ elm.remove(); }catch(e){ elm.style.display='none'; } });\n    };\n    const findTitleElement = (c)=> c.querySelector('.woocommerce-loop-product__title, .product-title, h2, h3, h4');\n    const findTitleAnchor  = (c)=> c.querySelector('.woocommerce-loop-product__title a, .product-title a, h2>a, h3>a, h4>a, a.woocommerce-LoopProduct-link, a.product-title, .product-link a');\n\n    const extractMeta = (c)=>{\n      const priceEl = c.querySelector('.price');\n      const extraEl = c.querySelector('.mk-short-description, .woocommerce-product-details__short-description, .excerpt, .product-excerpt, .entry-summary p, .horario');\n      const rawPrice = priceEl ? priceEl.textContent.trim() : '';\n      const nicePrice = rawPrice ? (\/^from|^regular\/i.test(rawPrice) ? rawPrice : `From ${rawPrice}`) : '';\n      const extraTxt  = extraEl ? extraEl.textContent.trim() : '';\n      return { nicePrice, extraTxt, priceEl, extraEl };\n    };\n    const stripResidualMeta = ({priceEl, extraEl})=>{ try{ priceEl && priceEl.remove(); }catch(e){} try{ extraEl && extraEl.remove(); }catch(e){} };\n\n    function createDayBlock(day, slug){\n      const sec=document.createElement('section'); sec.className='mimo-day-block';\n\n      const url = new URL(SEARCH_SLUG);\n      url.searchParams.set('min_date', day);\n      url.searchParams.set('max_date', day);\n      url.searchParams.set('embed','1');\n      if (slug) url.searchParams.set('product_cat', slug);\n\n      sec.innerHTML = `\n        <h3 class=\"mimo-day-title\">${prettyDate(day)}\n        <div class=\"mimo-loading\">Loading\u2026<\/script>\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u00ab Previous Next \u00bb All categoriesCooking classesFood tours This week Clear selection 0 selected Show availability Clear results<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"om_disable_all_campaigns":false,"_uag_custom_page_level_css":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"class_list":["post-2245","page","type-page","status-publish","hentry"],"aioseo_notices":[],"uagb_featured_image_src":{"full":false,"thumbnail":false,"medium":false,"medium_large":false,"large":false,"1536x1536":false,"2048x2048":false,"inspiro-featured-image":false,"inspiro-loop":false,"inspiro-loop@2x":false,"woocommerce_thumbnail":false,"woocommerce_single":false,"woocommerce_gallery_thumbnail":false},"uagb_author_info":{"display_name":"Lara Ibiricu","author_link":"https:\/\/sansebastiancookingclasses.com\/es\/author\/infomimo-eus\/"},"uagb_comment_info":0,"uagb_excerpt":"\u00ab Previous Next \u00bb All categoriesCooking classesFood tours This week Clear selection 0 selected Show availability Clear results","_links":{"self":[{"href":"https:\/\/sansebastiancookingclasses.com\/es\/wp-json\/wp\/v2\/pages\/2245","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sansebastiancookingclasses.com\/es\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/sansebastiancookingclasses.com\/es\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/sansebastiancookingclasses.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/sansebastiancookingclasses.com\/es\/wp-json\/wp\/v2\/comments?post=2245"}],"version-history":[{"count":1,"href":"https:\/\/sansebastiancookingclasses.com\/es\/wp-json\/wp\/v2\/pages\/2245\/revisions"}],"predecessor-version":[{"id":2246,"href":"https:\/\/sansebastiancookingclasses.com\/es\/wp-json\/wp\/v2\/pages\/2245\/revisions\/2246"}],"wp:attachment":[{"href":"https:\/\/sansebastiancookingclasses.com\/es\/wp-json\/wp\/v2\/media?parent=2245"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}