{"id":70927,"date":"2026-08-05T09:58:36","date_gmt":"2026-08-05T07:58:36","guid":{"rendered":"https:\/\/tickelia.com\/demo_2023\/?p=70927"},"modified":"2026-08-05T10:09:11","modified_gmt":"2026-08-05T08:09:11","slug":"calendario-prueba-2","status":"publish","type":"post","link":"https:\/\/tickelia.com\/demo_2023\/blog\/actualidad\/calendario-prueba-2\/","title":{"rendered":"Calendario prueba 2"},"content":{"rendered":"<div class=\"dlab-widget\">\r\n  <style>\r\n    \/* Todo escopado bajo .dlab-widget para no interferir con estilos globales de la p\u00e1gina.\r\n       No se define font-family, color de texto base, ni estilos de <button>\/<input>\/<select>:\r\n       heredan lo que ya tenga definido tu sitio para esos elementos. *\/\r\n\r\n    .dlab-widget {\r\n      --dlab-card: #ffffff;\r\n      --dlab-muted: #64748b;\r\n      --dlab-primary: #2563eb;\r\n      --dlab-primary-dark: #1d4ed8;\r\n      --dlab-border: #dbe3ef;\r\n      --dlab-soft: #eef4ff;\r\n      --dlab-danger: #fee2e2;\r\n      --dlab-danger-text: #991b1b;\r\n      --dlab-weekend: #f1f5f9;\r\n      --dlab-holiday: #fff1f2;\r\n      --dlab-workday: #ecfdf5;\r\n      --dlab-shadow: 0 18px 45px rgba(15, 23, 42, .08);\r\n      --dlab-radius: 18px;\r\n      max-width: 1180px;\r\n      margin: 0 auto;\r\n    }\r\n\r\n    .dlab-widget *, .dlab-widget *::before, .dlab-widget *::after { box-sizing: border-box; }\r\n\r\n    .dlab-widget .dlab-hero,\r\n    .dlab-widget .dlab-panel {\r\n      background: rgba(255, 255, 255, .9);\r\n      border: 1px solid rgba(219, 227, 239, .95);\r\n      border-radius: var(--dlab-radius);\r\n      box-shadow: var(--dlab-shadow);\r\n      padding: 24px;\r\n      margin-bottom: 20px;\r\n    }\r\n\r\n    .dlab-widget h2 {\r\n      margin: 0 0 16px;\r\n      font-size: 1.25rem;\r\n      letter-spacing: -0.02em;\r\n    }\r\n\r\n    .dlab-widget .dlab-subtitle,\r\n    .dlab-widget .dlab-note {\r\n      color: var(--dlab-muted);\r\n      margin: 0;\r\n      line-height: 1.55;\r\n    }\r\n\r\n    .dlab-widget .dlab-grid {\r\n      display: grid;\r\n      grid-template-columns: repeat(12, 1fr);\r\n      gap: 16px;\r\n      align-items: end;\r\n    }\r\n\r\n    .dlab-widget .dlab-field { display: flex; flex-direction: column; gap: 7px; }\r\n    .dlab-widget .dlab-span-2 { grid-column: span 2; }\r\n    .dlab-widget .dlab-span-3 { grid-column: span 3; }\r\n    .dlab-widget .dlab-span-4 { grid-column: span 4; }\r\n    .dlab-widget .dlab-span-6 { grid-column: span 6; }\r\n    .dlab-widget .dlab-span-12 { grid-column: span 12; }\r\n\r\n    .dlab-widget label {\r\n      font-size: .88rem;\r\n      font-weight: 700;\r\n    }\r\n\r\n    \/* Inputs\/select: solo layout (ancho, alto), sin colores\/tipograf\u00eda propios *\/\r\n    .dlab-widget select,\r\n    .dlab-widget input {\r\n      width: 100%;\r\n      height: 44px;\r\n      padding: 0 12px;\r\n    }\r\n\r\n    \/* Bot\u00f3n: solo dimensiones\/espaciado, sin color propio -> hereda el bot\u00f3n de tu web *\/\r\n    .dlab-widget button {\r\n      height: 44px;\r\n      padding: 0 18px;\r\n      cursor: pointer;\r\n    }\r\n\r\n    .dlab-widget button:disabled { cursor: not-allowed; }\r\n\r\n    .dlab-widget .dlab-status {\r\n      display: none;\r\n      margin-top: 14px;\r\n      border-radius: 12px;\r\n      padding: 12px 14px;\r\n      font-size: .95rem;\r\n      line-height: 1.45;\r\n    }\r\n\r\n    .dlab-widget .dlab-status.show { display: block; }\r\n    .dlab-widget .dlab-status.info { background: var(--dlab-soft); color: #1e40af; }\r\n    .dlab-widget .dlab-status.error { background: var(--dlab-danger); color: var(--dlab-danger-text); }\r\n\r\n    .dlab-widget .dlab-results {\r\n      display: grid;\r\n      grid-template-columns: repeat(4, 1fr);\r\n      gap: 14px;\r\n    }\r\n\r\n    .dlab-widget .dlab-metric {\r\n      border: 1px solid var(--dlab-border);\r\n      border-radius: 16px;\r\n      padding: 16px;\r\n      background: linear-gradient(180deg, #fff 0%, #f8fafc 100%);\r\n    }\r\n\r\n    .dlab-widget .dlab-metric small {\r\n      display: block;\r\n      color: var(--dlab-muted);\r\n      font-weight: 700;\r\n      margin-bottom: 6px;\r\n    }\r\n\r\n    .dlab-widget .dlab-metric strong {\r\n      display: block;\r\n      font-size: 2rem;\r\n      letter-spacing: -0.04em;\r\n    }\r\n\r\n    .dlab-widget .dlab-months {\r\n      display: grid;\r\n      grid-template-columns: repeat(auto-fit, minmax(285px, 1fr));\r\n      gap: 16px;\r\n    }\r\n\r\n    .dlab-widget .dlab-month {\r\n      border: 1px solid var(--dlab-border);\r\n      border-radius: 16px;\r\n      overflow: hidden;\r\n      background: #fff;\r\n    }\r\n\r\n    .dlab-widget .dlab-month-title {\r\n      padding: 12px 14px;\r\n      background: #f8fafc;\r\n      border-bottom: 1px solid var(--dlab-border);\r\n      font-weight: 900;\r\n      text-transform: capitalize;\r\n    }\r\n\r\n    .dlab-widget .dlab-weekdays,\r\n    .dlab-widget .dlab-days {\r\n      display: grid;\r\n      grid-template-columns: repeat(7, 1fr);\r\n    }\r\n\r\n    .dlab-widget .dlab-weekdays div {\r\n      padding: 8px 4px;\r\n      text-align: center;\r\n      font-size: .72rem;\r\n      color: var(--dlab-muted);\r\n      font-weight: 800;\r\n      background: #fbfdff;\r\n      border-bottom: 1px solid var(--dlab-border);\r\n    }\r\n\r\n    .dlab-widget .dlab-day {\r\n      min-height: 42px;\r\n      border-right: 1px solid #eef2f7;\r\n      border-bottom: 1px solid #eef2f7;\r\n      padding: 5px;\r\n      font-size: .8rem;\r\n      position: relative;\r\n    }\r\n\r\n    .dlab-widget .dlab-day:nth-child(7n) { border-right: 0; }\r\n    .dlab-widget .dlab-day.empty { background: #fbfdff; }\r\n    .dlab-widget .dlab-day.workday { background: var(--dlab-workday); }\r\n    .dlab-widget .dlab-day.weekend { background: var(--dlab-weekend); color: #64748b; }\r\n    .dlab-widget .dlab-day.holiday { background: var(--dlab-holiday); color: #9f1239; font-weight: 800; }\r\n    .dlab-widget .dlab-day.out { opacity: .36; }\r\n\r\n    .dlab-widget .dlab-dot {\r\n      position: absolute;\r\n      right: 5px;\r\n      bottom: 5px;\r\n      width: 6px;\r\n      height: 6px;\r\n      border-radius: 999px;\r\n      background: currentColor;\r\n    }\r\n\r\n    .dlab-widget div.dlab-holiday-list {\r\n      margin: 0;\r\n      padding: 0;\r\n      display: grid;\r\n      gap: 10px;\r\n    }\r\n\r\n    .dlab-widget div.dlab-holiday-row {\r\n      border: 1px solid var(--dlab-border);\r\n      border-radius: 14px;\r\n      padding: 11px 13px;\r\n      margin: 0;\r\n      background: #fff;\r\n      display: flex;\r\n      justify-content: space-between;\r\n      gap: 14px;\r\n      align-items: center;\r\n    }\r\n\r\n    .dlab-widget .dlab-badge {\r\n      display: inline-flex;\r\n      align-items: center;\r\n      border-radius: 999px;\r\n      padding: 4px 9px;\r\n      font-size: .75rem;\r\n      font-weight: 800;\r\n      background: #e0f2fe;\r\n      color: #075985;\r\n      white-space: nowrap;\r\n    }\r\n\r\n    .dlab-widget .dlab-legend {\r\n      display: flex;\r\n      flex-wrap: wrap;\r\n      gap: 10px;\r\n      margin-bottom: 14px;\r\n      color: var(--dlab-muted);\r\n      font-size: .86rem;\r\n    }\r\n\r\n    .dlab-widget .dlab-legend span {\r\n      display: inline-flex;\r\n      align-items: center;\r\n      gap: 6px;\r\n    }\r\n\r\n\r\n    .dlab-widget .dlab-note {\r\n      font-size: .86rem;\r\n      margin-top: 12px;\r\n    }\r\n\r\n    @media (max-width: 860px) {\r\n      .dlab-widget .dlab-span-3,\r\n      .dlab-widget .dlab-span-4,\r\n      .dlab-widget .dlab-span-6 { grid-column: span 12; }\r\n      .dlab-widget .dlab-results { grid-template-columns: repeat(2, 1fr); }\r\n    }\r\n\r\n    @media (max-width: 560px) {\r\n      .dlab-widget .dlab-hero,\r\n      .dlab-widget .dlab-panel { padding: 18px; }\r\n      .dlab-widget .dlab-results { grid-template-columns: 1fr; }\r\n    }\r\n  <\/style>\r\n\r\n  <section class=\"dlab-hero\">\r\n    <h2>Calculadora de d\u00edas laborables por comunidad aut\u00f3noma<\/h2>\r\n    <p class=\"dlab-subtitle\">\r\n      Calcula d\u00edas laborables entre dos fechas descontando s\u00e1bados, domingos y festivos nacionales\/auton\u00f3micos.\r\n    <\/p>\r\n  <\/section>\r\n\r\n  <section class=\"dlab-panel\">\r\n    <div class=\"dlab-grid\">\r\n      <div class=\"dlab-field dlab-span-3\">\r\n        <label for=\"dlabStartDate\">Fecha de inicio<\/label>\r\n        <input type=\"date\" id=\"dlabStartDate\" min=\"1975-01-01\" max=\"2075-12-31\" value=\"2026-01-01\">\r\n      <\/div>\r\n\r\n      <div class=\"dlab-field dlab-span-3\">\r\n        <label for=\"dlabEndDate\">Fecha final<\/label>\r\n        <input type=\"date\" id=\"dlabEndDate\" min=\"1975-01-01\" max=\"2075-12-31\" value=\"2026-12-31\">\r\n      <\/div>\r\n\r\n      <div class=\"dlab-field dlab-span-4\">\r\n        <label for=\"dlabRegion\">Comunidad aut\u00f3noma<\/label>\r\n        <select id=\"dlabRegion\"><\/select>\r\n      <\/div>\r\n\r\n      <div class=\"dlab-field dlab-span-2\">\r\n        <label for=\"dlabHours\">Horas\/d\u00eda<\/label>\r\n        <input type=\"number\" id=\"dlabHours\" min=\"0\" step=\"0.5\" value=\"8\">\r\n      <\/div>\r\n\r\n      <div class=\"dlab-field dlab-span-12\">\r\n        <button id=\"dlabCalculateBtn\" type=\"button\">Calcular d\u00edas laborables<\/button>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <div id=\"dlabStatus\" class=\"dlab-status\"><\/div>\r\n\r\n    <p class=\"dlab-note\">\r\n      Esta versi\u00f3n no incluye festivos municipales\/locales.\r\n    <\/p>\r\n  <\/section>\r\n\r\n  <section class=\"dlab-panel\" id=\"dlabSummaryPanel\" style=\"display:none;\">\r\n    <div class=\"dlab-results\">\r\n      <div class=\"dlab-metric\"><small>D\u00edas naturales<\/small><strong id=\"dlabTotalDays\">0<\/strong><\/div>\r\n      <div class=\"dlab-metric\"><small>D\u00edas laborables<\/small><strong id=\"dlabWorkDays\">0<\/strong><\/div>\r\n      <div class=\"dlab-metric\"><small>Festivos aplicados<\/small><strong id=\"dlabHolidayDays\">0<\/strong><\/div>\r\n      <div class=\"dlab-metric\"><small>Horas laborables<\/small><strong id=\"dlabWorkHours\">0<\/strong><\/div>\r\n    <\/div>\r\n  <\/section>\r\n\r\n  <section class=\"dlab-panel\" id=\"dlabHolidaysPanel\" style=\"display:none;\">\r\n    <h2>Festivos dentro del rango<\/h2>\r\n    <div id=\"dlabHolidayList\" class=\"dlab-holiday-list\"><\/div>\r\n  <\/section>\r\n\r\n  <section class=\"dlab-panel\" id=\"dlabCalendarPanel\" style=\"display:none;\">\r\n    <h2>Calendario visual<\/h2>\r\n    <div class=\"dlab-legend\">\r\n      <span>\r\n        <svg width=\"13\" height=\"13\" viewBox=\"0 0 13 13\" style=\"display:inline-block; vertical-align:middle; flex-shrink:0;\">\r\n          <rect x=\"0.5\" y=\"0.5\" width=\"12\" height=\"12\" rx=\"3\" fill=\"#ecfdf5\" stroke=\"#dbe3ef\"><\/rect>\r\n        <\/svg>\r\n        Laborable\r\n      <\/span>\r\n      <span>\r\n        <svg width=\"13\" height=\"13\" viewBox=\"0 0 13 13\" style=\"display:inline-block; vertical-align:middle; flex-shrink:0;\">\r\n          <rect x=\"0.5\" y=\"0.5\" width=\"12\" height=\"12\" rx=\"3\" fill=\"#f1f5f9\" stroke=\"#dbe3ef\"><\/rect>\r\n        <\/svg>\r\n        Fin de semana\r\n      <\/span>\r\n      <span>\r\n        <svg width=\"13\" height=\"13\" viewBox=\"0 0 13 13\" style=\"display:inline-block; vertical-align:middle; flex-shrink:0;\">\r\n          <rect x=\"0.5\" y=\"0.5\" width=\"12\" height=\"12\" rx=\"3\" fill=\"#fff1f2\" stroke=\"#dbe3ef\"><\/rect>\r\n        <\/svg>\r\n        Festivo\r\n      <\/span>\r\n    <\/div>\r\n    <div id=\"dlabMonths\" class=\"dlab-months\"><\/div>\r\n  <\/section>\r\n<\/div>\r\n\r\n<script>\r\n(function () {\r\n  const API_BASE = \"https:\/\/date.nager.at\/api\/v3\/PublicHolidays\";\r\n\r\n  const REGIONS = [\r\n    { code: \"ALL\", name: \"Toda Espa\u00f1a \/ solo festivos nacionales\" },\r\n    { code: \"ES-AN\", name: \"Andaluc\u00eda\" },\r\n    { code: \"ES-AR\", name: \"Arag\u00f3n\" },\r\n    { code: \"ES-AS\", name: \"Principado de Asturias\" },\r\n    { code: \"ES-CB\", name: \"Cantabria\" },\r\n    { code: \"ES-CE\", name: \"Ceuta\" },\r\n    { code: \"ES-CL\", name: \"Castilla y Le\u00f3n\" },\r\n    { code: \"ES-CM\", name: \"Castilla-La Mancha\" },\r\n    { code: \"ES-CN\", name: \"Canarias\" },\r\n    { code: \"ES-CT\", name: \"Catalu\u00f1a\" },\r\n    { code: \"ES-EX\", name: \"Extremadura\" },\r\n    { code: \"ES-GA\", name: \"Galicia\" },\r\n    { code: \"ES-IB\", name: \"Illes Balears\" },\r\n    { code: \"ES-MC\", name: \"Regi\u00f3n de Murcia\" },\r\n    { code: \"ES-MD\", name: \"Comunidad de Madrid\" },\r\n    { code: \"ES-ML\", name: \"Melilla\" },\r\n    { code: \"ES-NC\", name: \"Comunidad Foral de Navarra\" },\r\n    { code: \"ES-PV\", name: \"Pa\u00eds Vasco\" },\r\n    { code: \"ES-RI\", name: \"La Rioja\" },\r\n    { code: \"ES-VC\", name: \"Comunitat Valenciana\" }\r\n  ];\r\n\r\n  const els = {\r\n    startDate: document.getElementById(\"dlabStartDate\"),\r\n    endDate: document.getElementById(\"dlabEndDate\"),\r\n    region: document.getElementById(\"dlabRegion\"),\r\n    hours: document.getElementById(\"dlabHours\"),\r\n    calculateBtn: document.getElementById(\"dlabCalculateBtn\"),\r\n    status: document.getElementById(\"dlabStatus\"),\r\n    summaryPanel: document.getElementById(\"dlabSummaryPanel\"),\r\n    holidaysPanel: document.getElementById(\"dlabHolidaysPanel\"),\r\n    calendarPanel: document.getElementById(\"dlabCalendarPanel\"),\r\n    totalDays: document.getElementById(\"dlabTotalDays\"),\r\n    workDays: document.getElementById(\"dlabWorkDays\"),\r\n    holidayDays: document.getElementById(\"dlabHolidayDays\"),\r\n    workHours: document.getElementById(\"dlabWorkHours\"),\r\n    holidayList: document.getElementById(\"dlabHolidayList\"),\r\n    months: document.getElementById(\"dlabMonths\")\r\n  };\r\n\r\n  const cache = new Map();\r\n\r\n  function initRegions() {\r\n    els.region.innerHTML = \"\";\r\n    REGIONS.forEach(region => {\r\n      const opt = document.createElement(\"option\");\r\n      opt.value = region.code;\r\n      opt.textContent = region.name;\r\n      els.region.appendChild(opt);\r\n    });\r\n    els.region.value = \"ES-CT\";\r\n  }\r\n\r\n  function showStatus(message, type = \"info\") {\r\n    els.status.textContent = message;\r\n    els.status.className = `dlab-status show ${type}`;\r\n  }\r\n\r\n  function clearStatus() {\r\n    els.status.textContent = \"\";\r\n    els.status.className = \"dlab-status\";\r\n  }\r\n\r\n  async function fetchHolidays(year) {\r\n    if (cache.has(year)) return cache.get(year);\r\n    const url = `${API_BASE}\/${year}\/ES`;\r\n    const res = await fetch(url, { cache: \"force-cache\" });\r\n    if (!res.ok) throw new Error(`No se pudieron cargar los festivos de ${year}. C\u00f3digo: ${res.status}`);\r\n    const data = await res.json();\r\n    cache.set(year, data);\r\n    return data;\r\n  }\r\n\r\n  function yearsInRange(start, end) {\r\n    const startYear = new Date(start + \"T00:00:00\").getFullYear();\r\n    const endYear = new Date(end + \"T00:00:00\").getFullYear();\r\n    const years = [];\r\n    for (let y = startYear; y <= endYear; y++) years.push(y);\r\n    return years;\r\n  }\r\n\r\n  function validateDates(start, end) {\r\n    if (!start || !end) throw new Error(\"Selecciona fecha de inicio y fecha final.\");\r\n    if (new Date(start) > new Date(end)) throw new Error(\"La fecha final debe ser igual o posterior a la fecha de inicio.\");\r\n    const years = yearsInRange(start, end);\r\n    if (years.length > 8) throw new Error(\"Para evitar demasiadas llamadas a la API, usa un rango m\u00e1ximo de 8 a\u00f1os.\");\r\n  }\r\n\r\n  function appliesToRegion(holiday, regionCode) {\r\n    const counties = holiday.counties;\r\n    if (regionCode === \"ALL\") return !counties || counties.length === 0;\r\n    return !counties || counties.length === 0 || counties.includes(regionCode);\r\n  }\r\n\r\n  function normalizeHoliday(h) {\r\n    return {\r\n      date: h.date,\r\n      name: h.localName || h.name || \"Festivo\",\r\n      globalName: h.name || h.localName || \"Festivo\",\r\n      regionCodes: h.counties || [],\r\n      type: Array.isArray(h.types) ? h.types.join(\", \") : \"Public\"\r\n    };\r\n  }\r\n\r\n  async function loadHolidaysForRange(start, end, regionCode) {\r\n    const all = [];\r\n    for (const year of yearsInRange(start, end)) {\r\n      const data = await fetchHolidays(year);\r\n      all.push(...data.filter(h => appliesToRegion(h, regionCode)).map(normalizeHoliday));\r\n    }\r\n\r\n    const deduped = new Map();\r\n    all.forEach(h => deduped.set(`${h.date}|${h.name}`, h));\r\n\r\n    return [...deduped.values()]\r\n      .filter(h => h.date >= start && h.date <= end)\r\n      .sort((a, b) => a.date.localeCompare(b.date));\r\n  }\r\n\r\n  function eachDate(start, end, cb) {\r\n    const d = new Date(start + \"T00:00:00\");\r\n    const last = new Date(end + \"T00:00:00\");\r\n    while (d <= last) {\r\n      cb(new Date(d));\r\n      d.setDate(d.getDate() + 1);\r\n    }\r\n  }\r\n\r\n  function iso(d) {\r\n    return d.toISOString().slice(0, 10);\r\n  }\r\n\r\n  function isWeekend(d) {\r\n    const day = d.getDay();\r\n    return day === 0 || day === 6;\r\n  }\r\n\r\n  function formatDate(date) {\r\n    return new Date(date + \"T00:00:00\").toLocaleDateString(\"es-ES\", {\r\n      weekday: \"short\",\r\n      day: \"2-digit\",\r\n      month: \"short\",\r\n      year: \"numeric\"\r\n    });\r\n  }\r\n\r\n  function regionName(code) {\r\n    return REGIONS.find(r => r.code === code)?.name || code;\r\n  }\r\n\r\n  async function handleCalculate() {\r\n    const start = els.startDate.value;\r\n    const end = els.endDate.value;\r\n    const regionCode = els.region.value;\r\n\r\n    try {\r\n      validateDates(start, end);\r\n      els.calculateBtn.disabled = true;\r\n      showStatus(`Cargando festivos para ${regionName(regionCode)}...`);\r\n\r\n      const holidays = await loadHolidaysForRange(start, end, regionCode);\r\n      const holidayByDate = new Map();\r\n\r\n      holidays.forEach(h => {\r\n        if (!holidayByDate.has(h.date)) holidayByDate.set(h.date, []);\r\n        holidayByDate.get(h.date).push(h);\r\n      });\r\n\r\n      let total = 0;\r\n      let holidayCount = 0;\r\n      let workCount = 0;\r\n\r\n      eachDate(start, end, d => {\r\n        total++;\r\n        const date = iso(d);\r\n        const weekend = isWeekend(d);\r\n        const holiday = holidayByDate.has(date);\r\n\r\n        if (holiday && !weekend) holidayCount++;\r\n        if (!weekend && !holiday) workCount++;\r\n      });\r\n\r\n      els.totalDays.textContent = total;\r\n      els.workDays.textContent = workCount;\r\n      els.holidayDays.textContent = holidayCount;\r\n      els.workHours.textContent = String(workCount * Number(els.hours.value || 0)).replace(\".\", \",\");\r\n\r\n      renderHolidayList(holidays);\r\n      renderCalendar(start, end, holidayByDate);\r\n\r\n      els.summaryPanel.style.display = \"block\";\r\n      els.holidaysPanel.style.display = \"block\";\r\n      els.calendarPanel.style.display = \"block\";\r\n\r\n      clearStatus();\r\n    } catch (err) {\r\n      showStatus(err.message || \"Ha ocurrido un error al calcular.\", \"error\");\r\n    } finally {\r\n      els.calculateBtn.disabled = false;\r\n    }\r\n  }\r\n\r\n  function renderHolidayList(holidays) {\r\n    els.holidayList.innerHTML = \"\";\r\n\r\n    if (!holidays.length) {\r\n      const row = document.createElement(\"div\");\r\n      row.className = \"dlab-holiday-row\";\r\n      row.textContent = \"No hay festivos en el rango seleccionado.\";\r\n      els.holidayList.appendChild(row);\r\n      return;\r\n    }\r\n\r\n    holidays.forEach(h => {\r\n      const row = document.createElement(\"div\");\r\n      row.className = \"dlab-holiday-row\";\r\n\r\n      const left = document.createElement(\"div\");\r\n      left.innerHTML = `\r\n        <strong>${formatDate(h.date)}<\/strong><br>\r\n        <span>${escapeHtml(h.name)}<\/span>\r\n      `;\r\n\r\n      const badge = document.createElement(\"span\");\r\n      badge.className = \"dlab-badge\";\r\n      badge.textContent = h.regionCodes.length ? \"Auton\u00f3mico\" : \"Nacional\";\r\n\r\n      row.appendChild(left);\r\n      row.appendChild(badge);\r\n      els.holidayList.appendChild(row);\r\n    });\r\n  }\r\n\r\n  function renderCalendar(start, end, holidayByDate) {\r\n    els.months.innerHTML = \"\";\r\n\r\n    const startD = new Date(start + \"T00:00:00\");\r\n    const endD = new Date(end + \"T00:00:00\");\r\n    const cursor = new Date(startD.getFullYear(), startD.getMonth(), 1);\r\n\r\n    while (cursor <= endD) {\r\n      const monthEl = document.createElement(\"article\");\r\n      monthEl.className = \"dlab-month\";\r\n\r\n      const title = document.createElement(\"div\");\r\n      title.className = \"dlab-month-title\";\r\n      title.textContent = cursor.toLocaleDateString(\"es-ES\", { month: \"long\", year: \"numeric\" });\r\n      monthEl.appendChild(title);\r\n\r\n      const weekdays = document.createElement(\"div\");\r\n      weekdays.className = \"dlab-weekdays\";\r\n      [\"L\", \"M\", \"X\", \"J\", \"V\", \"S\", \"D\"].forEach(d => {\r\n        const el = document.createElement(\"div\");\r\n        el.textContent = d;\r\n        weekdays.appendChild(el);\r\n      });\r\n      monthEl.appendChild(weekdays);\r\n\r\n      const days = document.createElement(\"div\");\r\n      days.className = \"dlab-days\";\r\n\r\n      const firstDay = new Date(cursor.getFullYear(), cursor.getMonth(), 1);\r\n      const startOffset = (firstDay.getDay() + 6) % 7;\r\n\r\n      for (let i = 0; i < startOffset; i++) {\r\n        const empty = document.createElement(\"div\");\r\n        empty.className = \"dlab-day empty\";\r\n        days.appendChild(empty);\r\n      }\r\n\r\n      const daysInMonth = new Date(cursor.getFullYear(), cursor.getMonth() + 1, 0).getDate();\r\n\r\n      for (let day = 1; day <= daysInMonth; day++) {\r\n        const d = new Date(cursor.getFullYear(), cursor.getMonth(), day);\r\n        const date = iso(d);\r\n        const cell = document.createElement(\"div\");\r\n        const out = d < startD || d > endD;\r\n        const holiday = holidayByDate.has(date);\r\n        const weekend = isWeekend(d);\r\n\r\n        cell.className = `dlab-day ${holiday ? \"holiday\" : weekend ? \"weekend\" : \"workday\"} ${out ? \"out\" : \"\"}`;\r\n        cell.textContent = day;\r\n\r\n        if (holiday) {\r\n          cell.title = holidayByDate.get(date).map(h => h.name).join(\" \/ \");\r\n          const dot = document.createElement(\"span\");\r\n          dot.className = \"dlab-dot\";\r\n          cell.appendChild(dot);\r\n        }\r\n\r\n        days.appendChild(cell);\r\n      }\r\n\r\n      monthEl.appendChild(days);\r\n      els.months.appendChild(monthEl);\r\n      cursor.setMonth(cursor.getMonth() + 1);\r\n    }\r\n  }\r\n\r\n  function escapeHtml(str) {\r\n    return String(str).replace(\/[&<>\"']\/g, s => ({\r\n      \"&\": \"&amp;\",\r\n      \"<\": \"&lt;\",\r\n      \">\": \"&gt;\",\r\n      '\"': \"&quot;\",\r\n      \"'\": \"&#039;\"\r\n    }[s]));\r\n  }\r\n\r\n  els.calculateBtn.addEventListener(\"click\", handleCalculate);\r\n  initRegions();\r\n})();\r\n<\/script>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":18,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"set","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[533],"tags":[],"class_list":["post-70927","post","type-post","status-publish","format-standard","hentry","category-actualidad"],"acf":[],"lang":"es","translations":{"es":70927},"pll_sync_post":[],"_links":{"self":[{"href":"https:\/\/tickelia.com\/demo_2023\/wp-json\/wp\/v2\/posts\/70927","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tickelia.com\/demo_2023\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tickelia.com\/demo_2023\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tickelia.com\/demo_2023\/wp-json\/wp\/v2\/users\/18"}],"replies":[{"embeddable":true,"href":"https:\/\/tickelia.com\/demo_2023\/wp-json\/wp\/v2\/comments?post=70927"}],"version-history":[{"count":4,"href":"https:\/\/tickelia.com\/demo_2023\/wp-json\/wp\/v2\/posts\/70927\/revisions"}],"predecessor-version":[{"id":70935,"href":"https:\/\/tickelia.com\/demo_2023\/wp-json\/wp\/v2\/posts\/70927\/revisions\/70935"}],"wp:attachment":[{"href":"https:\/\/tickelia.com\/demo_2023\/wp-json\/wp\/v2\/media?parent=70927"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tickelia.com\/demo_2023\/wp-json\/wp\/v2\/categories?post=70927"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tickelia.com\/demo_2023\/wp-json\/wp\/v2\/tags?post=70927"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}