{"id":488,"date":"2026-04-01T09:38:00","date_gmt":"2026-04-01T08:38:00","guid":{"rendered":"https:\/\/willinghambaptist.org\/?page_id=488"},"modified":"2026-04-01T09:42:03","modified_gmt":"2026-04-01T08:42:03","slug":"willingham-baptist-church-calendar","status":"publish","type":"page","link":"https:\/\/willinghambaptist.org\/index.php\/willingham-baptist-church-calendar\/","title":{"rendered":"Willingham Baptist Church Calendar"},"content":{"rendered":"<div id=\"cp-shell\" class=\"calendar-plugin-shell\" data-mode=\"full\" style=\"border:1px solid #ddd;padding:12px;border-radius:8px;background:#f8fafc;\">\n  <div style=\"display:flex;justify-content:space-between;align-items:center;gap:12px;flex-wrap:wrap;\">\n    <div style=\"display:flex;gap:8px;align-items:center;\">\n      <span id=\"cp-auth-state\">Not logged in<\/span>\n      <button id=\"cp-open-login-btn\" type=\"button\">Login<\/button>\n      <button id=\"cp-logout-btn\" type=\"button\" style=\"display:none;\">Logout<\/button>\n      <a href=\"\/wbc\/caldav\/\">CalDAV<\/a>\n      <a href=\"\/wbc\/calendar.ics\">ICS<\/a>\n    <\/div>\n  <\/div>\n\n  <div style=\"display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:10px;\">\n    <button id=\"cp-prev-btn\" type=\"button\">&#x2190;<\/button>\n    <button id=\"cp-today-btn\" type=\"button\">Today<\/button>\n    <button id=\"cp-next-btn\" type=\"button\">&#x2192;<\/button>\n    <select id=\"cp-view\">\n      <option value=\"list\">List<\/option>\n      <option value=\"day\">Day<\/option>\n      <option value=\"week\">Week<\/option>\n      <option value=\"month\" selected>Month<\/option>\n      <option value=\"year\">Year<\/option>\n    <\/select>\n    <input id=\"cp-date\" type=\"date\" value=\"2026-05-15\" \/>\n    <label id=\"cp-future-wrap\" style=\"display:flex;gap:6px;align-items:center;\"><input id=\"cp-future-only\" type=\"checkbox\" checked \/> Future only<\/label>\n    <button id=\"cp-refresh-btn\" type=\"button\">Refresh<\/button>\n    <button id=\"cp-create-btn\" type=\"button\" style=\"display:none;\">Create Event<\/button>\n    <div style=\"margin-left:auto;min-width:190px;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\">\n      <label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Theme<\/label>\n      <select id=\"cp-theme\" title=\"Theme\" style=\"width:100%;border:0;outline:none;background:#fff;\">\n        <option value=\"editorial\">Editorial<\/option>\n        <option value=\"paper\">Warm Paper<\/option>\n        <option value=\"dashboard\">Modern Dashboard<\/option>\n        <option value=\"garden\">Seasonal Garden<\/option>\n        <option value=\"contrast\">High Contrast<\/option>\n      <\/select>\n    <\/div>\n  <\/div>\n\n  <p id=\"cp-status\" style=\"margin:10px 0 8px 0;\"><\/p>\n  <h3 id=\"cp-events-title\" style=\"margin:0 0 8px 0;\">Events<\/h3>\n  <div id=\"cp-view-panel\"><\/div>\n  <ul id=\"cp-public-list\" style=\"margin-top:8px;list-style:none;padding-left:0;\"><\/ul>\n\n  <div id=\"cp-auth-modal\" style=\"display:none;position:fixed;inset:0;background:rgba(0,0,0,0.35);z-index:2147483000;align-items:center;justify-content:center;padding:12px;box-sizing:border-box;\">\n    <div style=\"width:min(560px,100%);max-height:92vh;overflow:auto;background:#fff;border-radius:8px;padding:12px;\">\n      <h3 style=\"margin:0 0 8px 0;\">Account Login<\/h3>\n      <p id=\"cp-auth-status\" style=\"margin:0 0 8px 0;\"><\/p>\n      <div style=\"display:grid;grid-template-columns:1fr 1fr;gap:8px;\">\n        <input id=\"cp-login-email\" type=\"email\" placeholder=\"Email\" \/>\n        <input id=\"cp-login-password\" type=\"password\" placeholder=\"Password (8+ chars)\" \/>\n      <\/div>\n      <div style=\"display:grid;grid-template-columns:1fr auto;gap:8px;margin-top:8px;\">\n        <input id=\"cp-verify-token\" type=\"text\" placeholder=\"Verification token\" \/>\n        <button id=\"cp-verify-btn\" type=\"button\">Verify Email<\/button>\n      <\/div>\n      <div style=\"display:flex;gap:8px;flex-wrap:wrap;margin-top:8px;\">\n        <button id=\"cp-login-btn\" type=\"button\">Login<\/button>\n        <button id=\"cp-register-btn\" type=\"button\">Register<\/button>\n        <button id=\"cp-reset-request-btn\" type=\"button\">Reset Password<\/button>\n        <button id=\"cp-close-login-btn\" type=\"button\">Close<\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <div id=\"cp-editor-modal\" style=\"display:none;position:fixed;inset:0;background:rgba(0,0,0,0.35);z-index:2147483000;\">\n    <div style=\"max-width:900px;margin:3vh auto;background:#fff;border-radius:8px;padding:12px;max-height:94vh;overflow:auto;\">\n      <h3 id=\"cp-editor-title\" style=\"margin:0 0 8px 0;\">Create Event<\/h3>\n      <input id=\"cp-event-id\" type=\"hidden\" \/>\n      <div style=\"display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;\">\n        <div style=\"grid-column:1 \/ span 4;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Title<\/label><input id=\"cp-title\" type=\"text\" style=\"width:100%;border:0;outline:none;\" \/><\/div>\n        <div style=\"grid-column:1 \/ span 4;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Visibility<\/label><select id=\"cp-visibility\" style=\"width:100%;border:0;outline:none;background:#fff;\"><option value=\"public\">Public<\/option><option value=\"private\">Private<\/option><\/select><\/div>\n        <div style=\"grid-column:1 \/ span 2;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Category<\/label><input id=\"cp-category\" type=\"text\" style=\"width:100%;border:0;outline:none;\" \/><\/div>\n        <div style=\"grid-column:3 \/ span 2;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Location<\/label><input id=\"cp-location\" type=\"text\" style=\"width:100%;border:0;outline:none;\" \/><\/div>\n        <div style=\"grid-column:1 \/ span 4;\"><label style=\"display:inline-flex;align-items:center;gap:6px;\"><input id=\"cp-all-day\" type=\"checkbox\" \/> All Day Event<\/label><\/div>\n        <div style=\"grid-column:1 \/ span 1;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Start Date<\/label><input id=\"cp-start-date\" type=\"date\" style=\"width:100%;border:0;outline:none;\" \/><\/div>\n        <div style=\"grid-column:2 \/ span 1;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">End Date<\/label><input id=\"cp-end-date\" type=\"date\" style=\"width:100%;border:0;outline:none;\" \/><\/div>\n        <div id=\"cp-start-time-wrap\" style=\"grid-column:3 \/ span 1;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Start Time<\/label><input id=\"cp-start-time\" type=\"time\" style=\"width:100%;border:0;outline:none;\" \/><\/div>\n        <div id=\"cp-end-time-wrap\" style=\"grid-column:4 \/ span 1;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">End Time<\/label><input id=\"cp-end-time\" type=\"time\" style=\"width:100%;border:0;outline:none;\" \/><\/div>\n        <div style=\"grid-column:1 \/ span 4;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Repeat<\/label><select id=\"cp-repeat-type\" style=\"width:100%;border:0;outline:none;\"><option value=\"none\">No repeat<\/option><option value=\"daily\">Daily<\/option><option value=\"weekly\">Weekly<\/option><option value=\"monthly\">Monthly<\/option><option value=\"yearly\">Yearly<\/option><\/select><\/div>\n      <\/div>\n      <div id=\"cp-repeat-extra\" style=\"display:none;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:8px;margin-top:8px;\">\n        <div style=\"position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Every<\/label><div style=\"display:flex;align-items:center;gap:6px;\"><input id=\"cp-repeat-interval\" type=\"number\" min=\"1\" value=\"1\" style=\"width:90px;border:0;outline:none;\" \/><span id=\"cp-repeat-unit\" style=\"color:#555;font-size:13px;\"><\/span><\/div><\/div>\n        <div id=\"cp-monthly-nth-wrap\" style=\"display:none;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Monthly Pattern<\/label><select id=\"cp-monthly-nth-mode\" style=\"width:100%;border:0;outline:none;\"><option value=\"\">From start date<\/option><option value=\"day_of_month\">nth day of month<\/option><option value=\"weekday_of_month\">nth weekday of month<\/option><\/select><\/div>\n        <div id=\"cp-nth-day-wrap\" style=\"display:none;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Day Number<\/label><input id=\"cp-nth-day\" type=\"number\" min=\"1\" max=\"31\" style=\"width:100%;border:0;outline:none;\" \/><\/div>\n        <div id=\"cp-nth-weekday-wrap\" style=\"display:none;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Nth<\/label><select id=\"cp-nth-pos\" style=\"width:100%;border:0;outline:none;\"><option value=\"1\">1st<\/option><option value=\"2\">2nd<\/option><option value=\"3\">3rd<\/option><option value=\"4\">4th<\/option><option value=\"5\">5th<\/option><option value=\"-1\">Last<\/option><\/select><\/div>\n        <div id=\"cp-nth-weekday2-wrap\" style=\"display:none;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Weekday<\/label><select id=\"cp-nth-weekday\" style=\"width:100%;border:0;outline:none;\"><option value=\"0\">Sunday<\/option><option value=\"1\">Monday<\/option><option value=\"2\">Tuesday<\/option><option value=\"3\">Wednesday<\/option><option value=\"4\">Thursday<\/option><option value=\"5\">Friday<\/option><option value=\"6\">Saturday<\/option><\/select><\/div>\n        <div style=\"position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Repeat Until Mode<\/label><select id=\"cp-range-mode\" style=\"width:100%;border:0;outline:none;\"><option value=\"none\">No end<\/option><option value=\"count\">Count<\/option><option value=\"until\">Until<\/option><\/select><\/div>\n        <div style=\"position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Count<\/label><input id=\"cp-repeat-count\" type=\"number\" min=\"1\" style=\"width:100%;border:0;outline:none;\" \/><\/div>\n        <div style=\"position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Repeat Until Date<\/label><input id=\"cp-repeat-until\" type=\"date\" style=\"width:100%;border:0;outline:none;\" \/><\/div>\n      <\/div>\n      <div id=\"cp-occurrence-panel\" style=\"display:none;margin-top:8px;border:1px solid #c7c7c7;border-radius:6px;padding:8px;background:#fff;\">\n        <div style=\"display:flex;gap:8px;align-items:center;margin-bottom:6px;\">\n          <strong>Recurrence Preview<\/strong>\n          <button id=\"cp-occ-prev-btn\" type=\"button\">&#8592;<\/button>\n          <button id=\"cp-occ-next-btn\" type=\"button\">&#8594;<\/button>\n        <\/div>\n        <p id=\"cp-occurrence-hint\" style=\"margin:0 0 6px 0;color:#666;\"><\/p>\n        <div id=\"cp-occurrence-grid\" style=\"display:grid;grid-template-columns:repeat(3,minmax(200px,1fr));gap:8px;\"><\/div>\n        <input id=\"cp-occurrence-key-iso\" type=\"hidden\" \/>\n        <div style=\"margin-top:6px;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Occurrence<\/label><input id=\"cp-occurrence-key\" type=\"text\" readonly style=\"width:100%;border:0;outline:none;background:#fff;\" \/><\/div>\n        <div style=\"margin-top:8px;\"><button id=\"cp-delete-occ-confirm-btn\" type=\"button\" disabled>Delete Occurrence<\/button><\/div>\n      <\/div>\n      <div style=\"margin-top:8px;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Description<\/label><textarea id=\"cp-description\" style=\"width:100%;min-height:60px;border:0;outline:none;resize:vertical;\"><\/textarea><\/div>\n      <p id=\"cp-editor-status\" style=\"margin:8px 0 0 0;\"><\/p>\n      <div style=\"display:flex;gap:8px;flex-wrap:wrap;margin-top:8px;\">\n        <button id=\"cp-editor-create-btn\" type=\"button\">Create<\/button>\n        <button id=\"cp-update-btn\" type=\"button\" disabled>Update<\/button>\n        <button id=\"cp-delete-btn\" type=\"button\" disabled>Delete<\/button>\n        <button id=\"cp-editor-close-btn\" type=\"button\">Close<\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <div id=\"cp-details-modal\" style=\"display:none;position:fixed;inset:0;background:rgba(0,0,0,0.35);z-index:2147483000;\">\n    <div style=\"max-width:900px;margin:4vh auto;background:#fff;border-radius:8px;padding:12px;max-height:90vh;overflow:auto;\">\n      <h3 style=\"margin:0 0 8px 0;\">Event Details<\/h3>\n      <div style=\"display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px;\">\n        <div style=\"grid-column:1 \/ span 4;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Title<\/label><input id=\"cp-details-title\" type=\"text\" readonly style=\"width:100%;border:0;outline:none;background:#fff;\" \/><\/div>\n        <div style=\"grid-column:1 \/ span 4;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Visibility<\/label><input id=\"cp-details-visibility\" type=\"text\" readonly style=\"width:100%;border:0;outline:none;background:#fff;\" \/><\/div>\n        <div style=\"grid-column:1 \/ span 2;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Category<\/label><input id=\"cp-details-category\" type=\"text\" readonly style=\"width:100%;border:0;outline:none;background:#fff;\" \/><\/div>\n        <div style=\"grid-column:3 \/ span 2;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Location<\/label><input id=\"cp-details-location\" type=\"text\" readonly style=\"width:100%;border:0;outline:none;background:#fff;\" \/><\/div>\n        <div style=\"grid-column:1 \/ span 2;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Start<\/label><input id=\"cp-details-start\" type=\"text\" readonly style=\"width:100%;border:0;outline:none;background:#fff;\" \/><\/div>\n        <div style=\"grid-column:3 \/ span 2;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">End<\/label><input id=\"cp-details-end\" type=\"text\" readonly style=\"width:100%;border:0;outline:none;background:#fff;\" \/><\/div>\n      <\/div>\n      <div style=\"margin-top:8px;position:relative;border:1px solid #c7c7c7;border-radius:6px;padding:14px 8px 6px 8px;background:#fff;\"><label style=\"position:absolute;top:-8px;left:8px;font-size:11px;background:#fff;padding:0 4px;color:#666;\">Description<\/label><textarea id=\"cp-details-description\" readonly style=\"width:100%;min-height:60px;border:0;outline:none;resize:vertical;background:#fff;\"><\/textarea><\/div>\n      <div style=\"display:flex;justify-content:flex-end;margin-top:8px;\">\n        <button id=\"cp-details-close-btn\" type=\"button\">Cancel<\/button>\n      <\/div>\n    <\/div>\n  <\/div>\n\n  <script>(function(){\n    const ns=\"calendar\/v1\";\n    const api=(p,o)=>fetch((window.location.origin||\"\")+(\"\/wp-json\/\"+ns+p),o||{});\n    const s=id=>document.getElementById(id);\n    let auth=null;\n    let me=null;\n    let lastItems=[];\n\n    const setStatus=(m,e)=>{const x=s(\"cp-status\"); x.textContent=m||\"\"; x.style.color=e?\"#a00\":\"#060\";};\n    const setAuthStatus=(m,e)=>{const x=s(\"cp-auth-status\"); x.textContent=m||\"\"; x.style.color=e?\"#a00\":\"#060\";};\n    const setEditorStatus=(m,e)=>{const x=s(\"cp-editor-status\"); x.textContent=m||\"\"; x.style.color=e?\"#a00\":\"#060\";};\n    const authHeaders=()=>auth?{Authorization:\"Basic \"+btoa(auth.email+\":\"+auth.password)}:{};\n    const ymd=(iso)=>String(iso||\"\").slice(0,10);\n    const hm=(iso)=>String(iso||\"\").slice(11,16);\n    const esc=(v)=>{const d=document.createElement(\"div\"); d.textContent=v==null?\"\":String(v); return d.innerHTML;};\n    const localYmd=(d)=>{const p=(n)=>String(n).padStart(2,\"0\"); return d.getFullYear()+\"-\"+p(d.getMonth()+1)+\"-\"+p(d.getDate());};\n    const dmy=(d)=>{const p=(n)=>String(n).padStart(2,\"0\"); return p(d.getDate())+\"\/\"+p(d.getMonth()+1)+\"\/\"+d.getFullYear();};\n    const longDate=(iso)=>{\n      if(!iso){return \"\";}\n      const d=new Date(iso);\n      if(Number.isNaN(d.getTime())){return ymd(iso);}\n      return d.toLocaleDateString(\"en-GB\",{day:\"numeric\",month:\"long\",year:\"numeric\"});\n    };\n    const timeValue=(iso)=>{\n      if(!iso){return \"\";}\n      const d=new Date(iso);\n      if(Number.isNaN(d.getTime())){return \"\";}\n      let h=d.getHours();\n      const m=d.getMinutes();\n      const mer=h>=12?\"pm\":\"am\";\n      h=h%12;\n      if(h===0){h=12;}\n      if(m===0){return `${h}${mer}`;}\n      return `${h}.${String(m).padStart(2,\"0\")}${mer}`;\n    };\n    const timeRange=(startIso,endIso)=>{\n      const s=new Date(startIso);\n      const e=new Date(endIso);\n      if(Number.isNaN(s.getTime()) || Number.isNaN(e.getTime())){return \"\";}\n      const sm=s.getHours()>=12?\"pm\":\"am\";\n      const em=e.getHours()>=12?\"pm\":\"am\";\n      let sv=timeValue(startIso);\n      const ev=timeValue(endIso);\n      if(sm===em){sv=sv.replace(\/(am|pm)$\/,\"\");}\n      return `${sv}\u2013${ev}`;\n    };\n    const itemId=(it)=>String(it.event_id||it.id||\"\");\n    const futureWrap=()=>s(\"cp-future-wrap\");\n    const monthNames=[\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"];\n    const themeKey=\"calendar_plugin_theme\";\n    const themes={\n      editorial:{shellBg:\"#f8fafc\",border:\"#cbd5e1\",headBg:\"#eff6ff\",cellBg:\"#ffffff\",mutedBg:\"#f1f5f9\",text:\"#0f172a\",mutedText:\"#475569\",accent:\"#2563eb\"},\n      paper:{shellBg:\"#fdf8f0\",border:\"#d6c3a7\",headBg:\"#faefe1\",cellBg:\"#fffdf8\",mutedBg:\"#f6efe4\",text:\"#3b2f2f\",mutedText:\"#6b5b4b\",accent:\"#b45309\"},\n      dashboard:{shellBg:\"#f6f8fb\",border:\"#d1d9e6\",headBg:\"#e6f4f1\",cellBg:\"#ffffff\",mutedBg:\"#edf2f7\",text:\"#111827\",mutedText:\"#4b5563\",accent:\"#0f766e\"},\n      garden:{shellBg:\"#f5fbf7\",border:\"#c8decf\",headBg:\"#e7f5ea\",cellBg:\"#ffffff\",mutedBg:\"#ecf6ef\",text:\"#1f3b2d\",mutedText:\"#4f6b5f\",accent:\"#3f7d20\"},\n      contrast:{shellBg:\"#ffffff\",border:\"#0f172a\",headBg:\"#e2e8f0\",cellBg:\"#ffffff\",mutedBg:\"#f8fafc\",text:\"#0f172a\",mutedText:\"#334155\",accent:\"#ea580c\"},\n    };\n    let currentThemeName=\"editorial\";\n    const theme=()=>themes[currentThemeName]||themes.editorial;\n    let occCursor=new Date();\n    let selectedOccurrenceDate=\"\";\n    let pendingDeletedOccurrenceKeys=[];\n\n    const applyTheme=()=>{\n      const t=theme();\n      const shell=s(\"cp-shell\");\n      shell.style.background=t.shellBg;\n      shell.style.borderColor=t.border;\n      shell.style.color=t.text;\n      s(\"cp-status\").style.color=t.mutedText;\n    };\n\n    const setAuthUi=()=>{\n      s(\"cp-auth-state\").textContent=me?(\"Logged in as \"+(me.email||\"\")):\"Not logged in\";\n      s(\"cp-open-login-btn\").style.display=me?\"none\":\"inline-block\";\n      s(\"cp-logout-btn\").style.display=me?\"inline-block\":\"none\";\n      s(\"cp-create-btn\").style.display=me?\"inline-block\":\"none\";\n    };\n\n    const setDateInput=(d)=>{s(\"cp-date\").value=(new Date(d.getTime()-d.getTimezoneOffset()*60000)).toISOString().slice(0,10);};\n    const currentDate=()=>new Date((s(\"cp-date\").value||new Date().toISOString().slice(0,10))+\"T00:00:00\");\n    const stepDate=(dir)=>{const d=currentDate(); const v=s(\"cp-view\").value; if(v===\"day\"){d.setDate(d.getDate()+dir);} else if(v===\"week\"){d.setDate(d.getDate()+dir*7);} else if(v===\"month\"){d.setMonth(d.getMonth()+dir);} else if(v===\"year\"){d.setFullYear(d.getFullYear()+dir);} else {d.setDate(d.getDate()+dir);} setDateInput(d); loadPublic();};\n\n    const toLocalParts=(iso)=>{\n      const d=new Date(String(iso||\"\"));\n      if(Number.isNaN(d.getTime())){return {date:\"\",time:\"\"};}\n      const p=(n)=>String(n).padStart(2,\"0\");\n      return {date:d.getFullYear()+\"-\"+p(d.getMonth()+1)+\"-\"+p(d.getDate()),time:p(d.getHours())+\":\"+p(d.getMinutes())};\n    };\n    const friendlyDateTime=(iso)=>{\n      const d=new Date(String(iso||\"\"));\n      if(Number.isNaN(d.getTime())){return \"\";}\n      const p=(n)=>String(n).padStart(2,\"0\");\n      return dmy(d)+\" \"+p(d.getHours())+\":\"+p(d.getMinutes());\n    };\n    const detailsDateTime=(iso,allDay)=>{\n      if(!iso){return \"\";}\n      if(allDay){return String(iso).slice(0,10);}\n      return friendlyDateTime(iso);\n    };\n    const repeatUnitLabel=()=>{\n      const rt=s(\"cp-repeat-type\").value;\n      const n=Math.max(1,parseInt(s(\"cp-repeat-interval\").value||\"1\",10)||1);\n      const unit=rt===\"daily\"?\"day\":(rt===\"weekly\"?\"week\":(rt===\"monthly\"?\"month\":(rt===\"yearly\"?\"year\":\"\")));\n      if(unit===\"\"){return \"\";}\n      return n===1?unit:(unit+\"s\");\n    };\n\n    const applyAllDayVisibility=()=>{\n      const allDay=!!s(\"cp-all-day\").checked;\n      s(\"cp-start-time-wrap\").style.display=allDay?\"none\":\"block\";\n      s(\"cp-end-time-wrap\").style.display=allDay?\"none\":\"block\";\n    };\n\n    const syncRepeatUi=()=>{\n      const rt=s(\"cp-repeat-type\").value;\n      const rm=s(\"cp-range-mode\").value;\n      const isRepeat=rt!==\"none\";\n      const hasId=!!s(\"cp-event-id\").value.trim();\n      s(\"cp-repeat-extra\").style.display=isRepeat?\"grid\":\"none\";\n      s(\"cp-monthly-nth-wrap\").style.display=rt===\"monthly\"?\"block\":\"none\";\n      const nthMode=s(\"cp-monthly-nth-mode\").value;\n      const showNthDay=rt===\"monthly\" && nthMode===\"day_of_month\";\n      const showNthWeekday=rt===\"monthly\" && nthMode===\"weekday_of_month\";\n      s(\"cp-nth-day-wrap\").style.display=showNthDay?\"block\":\"none\";\n      s(\"cp-nth-weekday-wrap\").style.display=showNthWeekday?\"block\":\"none\";\n      s(\"cp-nth-weekday2-wrap\").style.display=showNthWeekday?\"block\":\"none\";\n      s(\"cp-repeat-count\").parentElement.style.display=(isRepeat && rm===\"count\")?\"block\":\"none\";\n      s(\"cp-repeat-until\").parentElement.style.display=(isRepeat && rm===\"until\")?\"block\":\"none\";\n      s(\"cp-occurrence-panel\").style.display=isRepeat?\"block\":\"none\";\n      s(\"cp-repeat-unit\").textContent=isRepeat?repeatUnitLabel():\"\";\n      s(\"cp-occurrence-hint\").textContent=isRepeat\n        ? (hasId ? \"Select an occurrence to delete it from the recurrence.\" : \"Preview shows upcoming generated occurrences.\")\n        : \"\";\n      if(!isRepeat){\n        s(\"cp-occurrence-grid\").innerHTML=\"\";\n        s(\"cp-occurrence-key-iso\").value=\"\";\n        s(\"cp-occurrence-key\").value=\"\";\n        selectedOccurrenceDate=\"\";\n      }\n    };\n\n    const updateEditorButtons=()=>{\n      const titleOk=!!s(\"cp-title\").value.trim();\n      const startDate=s(\"cp-start-date\").value.trim();\n      const endDateRaw=s(\"cp-end-date\").value.trim();\n      const endDate=endDateRaw||startDate;\n      const allDay=!!s(\"cp-all-day\").checked;\n      const startTime=s(\"cp-start-time\").value.trim();\n      const endTime=s(\"cp-end-time\").value.trim();\n      let validDateTime=false;\n      if(startDate && endDate && endDate>=startDate){\n        if(allDay){\n          validDateTime=true;\n        } else if(startTime && endTime){\n          validDateTime=endDate>startDate || endTime>=startTime;\n        }\n      }\n      const hasCore=titleOk && validDateTime;\n      const hasId=!!s(\"cp-event-id\").value.trim();\n      const hasOcc=!!s(\"cp-occurrence-key-iso\").value.trim();\n      s(\"cp-editor-create-btn\").disabled=!me || !hasCore || hasId;\n      s(\"cp-update-btn\").disabled=!me || !hasCore || !hasId;\n      s(\"cp-delete-btn\").disabled=!me || !hasId;\n      s(\"cp-delete-occ-confirm-btn\").disabled=!me || s(\"cp-repeat-type\").value===\"none\" || !hasOcc;\n    };\n\n    const clearEditor=()=>{\n      s(\"cp-event-id\").value=\"\";\n      [\"cp-title\",\"cp-description\",\"cp-location\",\"cp-category\",\"cp-occurrence-key\"].forEach(k=>s(k).value=\"\");\n      s(\"cp-visibility\").value=\"public\";\n      s(\"cp-occurrence-key-iso\").value=\"\";\n      s(\"cp-all-day\").checked=false;\n      s(\"cp-repeat-type\").value=\"none\";\n      s(\"cp-repeat-interval\").value=\"1\";\n      s(\"cp-range-mode\").value=\"none\";\n      s(\"cp-repeat-count\").value=\"\";\n      s(\"cp-repeat-until\").value=\"\";\n      s(\"cp-monthly-nth-mode\").value=\"\";\n      s(\"cp-nth-day\").value=\"\";\n      s(\"cp-nth-pos\").value=\"1\";\n      s(\"cp-nth-weekday\").value=\"0\";\n      s(\"cp-start-date\").value=\"\";\n      s(\"cp-end-date\").value=\"\";\n      s(\"cp-start-time\").value=\"\";\n      s(\"cp-end-time\").value=\"\";\n      selectedOccurrenceDate=\"\";\n      pendingDeletedOccurrenceKeys=[];\n      s(\"cp-occurrence-panel\").style.display=\"none\";\n      s(\"cp-editor-title\").textContent=\"Create Event\";\n      occCursor=new Date();\n      setEditorStatus(\"\",false);\n      applyAllDayVisibility();\n      syncRepeatUi();\n      updateEditorButtons();\n    };\n\n    const openEditorCreate=()=>{\n      if(!me){setStatus(\"Login required\",true); return;}\n      clearEditor();\n      s(\"cp-editor-modal\").style.display=\"block\";\n    };\n\n    const openEditorCreateAt=(dateYmd)=>{\n      if(!me){setStatus(\"Login required\",true); return;}\n      clearEditor();\n      s(\"cp-start-date\").value=dateYmd||\"\";\n      s(\"cp-end-date\").value=dateYmd||\"\";\n      updateEditorButtons();\n      s(\"cp-editor-modal\").style.display=\"block\";\n    };\n\n    const openDetailsForItem=(it)=>{\n      s(\"cp-details-title\").value=it.title||\"\";\n      s(\"cp-details-visibility\").value=(it.visibility||\"public\")===\"private\"?\"Private\":\"Public\";\n      s(\"cp-details-category\").value=it.category||\"\";\n      s(\"cp-details-location\").value=it.location||\"\";\n      s(\"cp-details-start\").value=detailsDateTime(it.occurrence_start||it.start_datetime,!!it.all_day_event);\n      s(\"cp-details-end\").value=detailsDateTime(it.occurrence_end||it.end_datetime,!!it.all_day_event);\n      s(\"cp-details-description\").value=it.description||\"\";\n      s(\"cp-details-modal\").style.display=\"block\";\n    };\n\n    const openEditorForItem=async(it)=>{\n      if(!me){\n        openDetailsForItem(it);\n        return;\n      }\n      let source=it;\n      const id=itemId(it);\n      if(id){\n        try{\n          const r=await api(\"\/events\/\"+id,{headers:authHeaders()});\n          const p=await r.json();\n          if(r.ok && p && p.data){source=Object.assign({},it,p.data);}\n        }catch(_e){}\n      }\n      clearEditor();\n      s(\"cp-editor-title\").textContent=\"Edit Event\";\n      s(\"cp-event-id\").value=itemId(source);\n      s(\"cp-title\").value=source.title||\"\";\n      s(\"cp-visibility\").value=source.visibility===\"private\"?\"private\":\"public\";\n      s(\"cp-description\").value=source.description||\"\";\n      s(\"cp-location\").value=source.location||\"\";\n      s(\"cp-category\").value=source.category||\"\";\n      s(\"cp-repeat-type\").value=source.repeat_type||\"none\";\n      s(\"cp-repeat-interval\").value=source.repeat_interval||1;\n      s(\"cp-range-mode\").value=source.repeat_range_mode||\"none\";\n      s(\"cp-repeat-count\").value=source.repeat_count||\"\";\n      s(\"cp-repeat-until\").value=source.repeat_until||\"\";\n      s(\"cp-monthly-nth-mode\").value=source.repeat_nth_mode||\"\";\n      s(\"cp-nth-day\").value=source.repeat_nth_day||\"\";\n      s(\"cp-nth-pos\").value=source.repeat_nth_pos||\"1\";\n      s(\"cp-nth-weekday\").value=(source.repeat_nth_weekday===null||source.repeat_nth_weekday===undefined)?\"0\":String(source.repeat_nth_weekday);\n      s(\"cp-occurrence-key-iso\").value=(it.occurrence_start||\"\");\n      s(\"cp-occurrence-key\").value=friendlyDateTime(it.occurrence_start||\"\");\n      pendingDeletedOccurrenceKeys=[];\n      const st=toLocalParts(source.start_datetime||it.occurrence_start);\n      const en=toLocalParts(source.end_datetime||it.occurrence_end);\n      s(\"cp-all-day\").checked=!!source.all_day_event;\n      s(\"cp-start-date\").value=st.date;\n      s(\"cp-start-time\").value=st.time;\n      s(\"cp-end-date\").value=en.date;\n      s(\"cp-end-time\").value=en.time;\n      occCursor=new Date((source.start_datetime||new Date().toISOString()).slice(0,10)+\"T00:00:00\");\n      selectedOccurrenceDate=\"\";\n      applyAllDayVisibility();\n      syncRepeatUi();\n      updateEditorButtons();\n      if(s(\"cp-repeat-type\").value!==\"none\"){loadOccurrenceChooser();}\n      s(\"cp-editor-modal\").style.display=\"block\";\n    };\n\n    const formPayload=()=>{\n      const title=s(\"cp-title\").value.trim();\n      const startDate=s(\"cp-start-date\").value;\n      const endDateRaw=s(\"cp-end-date\").value;\n      const allDay=!!s(\"cp-all-day\").checked;\n      const startTime=s(\"cp-start-time\").value;\n      const endTime=s(\"cp-end-time\").value;\n      const endDate=endDateRaw||startDate;\n      if(title===\"\"){return {ok:false,message:\"Title is required\"};}\n      if(!startDate){return {ok:false,message:\"Start date is required\"};}\n      if(!allDay && !startTime){return {ok:false,message:\"Start time is required\"};}\n      if(!allDay && !endTime){return {ok:false,message:\"End time is required\"};}\n      const startIso=allDay?(startDate+\"T00:00:00+00:00\"):new Date(startDate+\"T\"+startTime).toISOString();\n      const endIso=allDay?(endDate+\"T00:00:00+00:00\"):new Date(endDate+\"T\"+endTime).toISOString();\n      if(Number.isNaN(new Date(startIso).getTime()) || Number.isNaN(new Date(endIso).getTime())){return {ok:false,message:\"Invalid date\/time values\"};}\n      if(new Date(endIso).getTime()<new Date(startIso).getTime()){return {ok:false,message:\"End must be at or after start\"};}\n      const repeatType=s(\"cp-repeat-type\").value;\n      const repeatRangeMode=repeatType===\"none\" ? \"none\" : s(\"cp-range-mode\").value;\n      const nthMode=s(\"cp-monthly-nth-mode\").value;\n      return {\n        ok:true,\n        payload:{\n          title:title,\n          visibility:s(\"cp-visibility\").value===\"private\"?\"private\":\"public\",\n          description:s(\"cp-description\").value,\n          location:s(\"cp-location\").value,\n          category:s(\"cp-category\").value,\n          all_day_event:allDay,\n          start_datetime:startIso,\n          end_datetime:endIso,\n          repeat_type:repeatType,\n          repeat_interval:repeatType===\"none\" ? 1 : parseInt(s(\"cp-repeat-interval\").value||\"1\",10),\n          repeat_nth_mode:repeatType===\"monthly\" ? nthMode : \"\",\n          repeat_nth_day:(repeatType===\"monthly\" && nthMode===\"day_of_month\" && s(\"cp-nth-day\").value)?parseInt(s(\"cp-nth-day\").value,10):null,\n          repeat_nth_pos:(repeatType===\"monthly\" && nthMode===\"weekday_of_month\" && s(\"cp-nth-pos\").value)?parseInt(s(\"cp-nth-pos\").value,10):null,\n          repeat_nth_weekday:(repeatType===\"monthly\" && nthMode===\"weekday_of_month\")?parseInt(s(\"cp-nth-weekday\").value||\"0\",10):null,\n          repeat_range_mode:repeatRangeMode,\n          repeat_count:(repeatType!==\"none\" && repeatRangeMode===\"count\" && s(\"cp-repeat-count\").value)?parseInt(s(\"cp-repeat-count\").value,10):null,\n          repeat_until:(repeatType!==\"none\" && repeatRangeMode===\"until\") ? (s(\"cp-repeat-until\").value||null) : null,\n          deleted_occurrence_keys:pendingDeletedOccurrenceKeys.slice()\n        }\n      };\n    };\n\n    const loadOccurrenceChooser=async()=>{\n      const id=s(\"cp-event-id\").value;\n      const from=new Date(occCursor.getFullYear(),occCursor.getMonth(),1);\n      const fromS=localYmd(from);\n      let r;\n      if(id){\n        r=await api(\"\/events\/\"+id+\"\/occurrences?from=\"+encodeURIComponent(fromS)+\"&months=3\",{headers:authHeaders()});\n      } else {\n        const built=formPayload();\n        if(!built.ok){\n          s(\"cp-occurrence-grid\").innerHTML=\"\";\n          s(\"cp-occurrence-key-iso\").value=\"\";\n          s(\"cp-occurrence-key\").value=\"\";\n          updateEditorButtons();\n          return;\n        }\n        r=await api(\"\/events\/preview-occurrences\",{method:\"POST\",headers:{\"Content-Type\":\"application\/json\"},body:JSON.stringify({event:built.payload,from:fromS,months:3})});\n      }\n      const p=await r.json();\n      if(!r.ok){setEditorStatus((p.error&&p.error.message)||\"Failed to load occurrences\",true); return;}\n      const list=p.data||[];\n      const dayToKey=new Map();\n      list.forEach(x=>{const d=(x.occurrence_start||\"\").slice(0,10); if(d && !dayToKey.has(d)){dayToKey.set(d,x.occurrence_start);}});\n      if(selectedOccurrenceDate && !dayToKey.has(selectedOccurrenceDate)){\n        selectedOccurrenceDate=\"\";\n      }\n      if(selectedOccurrenceDate && dayToKey.has(selectedOccurrenceDate)){\n        const iso=dayToKey.get(selectedOccurrenceDate)||\"\";\n        s(\"cp-occurrence-key-iso\").value=iso;\n        s(\"cp-occurrence-key\").value=friendlyDateTime(iso);\n      } else {\n        s(\"cp-occurrence-key-iso\").value=\"\";\n        s(\"cp-occurrence-key\").value=\"\";\n      }\n      const cells=[];\n      for(let m=0;m<3;m++){\n        const d=new Date(from.getFullYear(),from.getMonth()+m,1);\n        const y=d.getFullYear(), mo=d.getMonth();\n        const first=new Date(y,mo,1), off=(first.getDay()+6)%7, dim=new Date(y,mo+1,0).getDate();\n        let monthCells=\"\";\n        for(let i=0;i<off;i++){\n          const weekend=(i%7)>=5;\n          monthCells+=`<div style=\"border:1px solid #eee;border-radius:4px;min-height:22px;background:${weekend?'#fef2f2':'#f5f5f5'};\"><\/div>`;\n        }\n        for(let day=1; day<=dim; day++){\n          const dt=new Date(y,mo,day); const k=localYmd(dt); const has=dayToKey.has(k);\n          const selected=(k===selectedOccurrenceDate);\n          const weekend=((off+day-1)%7)>=5;\n          const baseBg=weekend?'#fff1f2':'#f5f5f5';\n          monthCells+=`<div style=\"border:1px solid ${selected?'#2563eb':(has?'#67e8f9':'#eee')};border-radius:4px;min-height:22px;padding:2px;text-align:center;background:${selected?'#dbeafe':(has?'#ecfeff':baseBg)};\"><div data-occ-date=\"${k}\" style=\"cursor:${has?'pointer':'default'};font-weight:${selected?700:400};\">${day}<\/div><\/div>`;\n        }\n        cells.push(`<div style=\"border:1px solid #ddd;padding:6px;border-radius:6px;\"><h4 style=\"margin:2px 0 6px 0;\">${d.toLocaleString('en-GB',{month:'short',year:'numeric'})}<\/h4><div style=\"display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:3px;\">${monthCells}<\/div><\/div>`);\n      }\n      s(\"cp-occurrence-grid\").innerHTML=cells.join(\"\");\n      Array.from(s(\"cp-occurrence-grid\").querySelectorAll(\"[data-occ-date]\")).forEach(el=>el.addEventListener(\"click\",()=>{\n        const k=el.getAttribute(\"data-occ-date\")||\"\";\n        if(!dayToKey.has(k)){return;}\n        if(selectedOccurrenceDate===k){\n          selectedOccurrenceDate=\"\";\n          s(\"cp-occurrence-key-iso\").value=\"\";\n          s(\"cp-occurrence-key\").value=\"\";\n        } else {\n          selectedOccurrenceDate=k;\n          const iso=dayToKey.get(k)||\"\";\n          s(\"cp-occurrence-key-iso\").value=iso;\n          s(\"cp-occurrence-key\").value=friendlyDateTime(iso);\n        }\n        loadOccurrenceChooser();\n      }));\n      updateEditorButtons();\n    };\n\n    const rowsForDay=(items)=>{\n      const t=theme();\n      return items.map(it=>`<div data-cp-id=\"${esc(itemId(it))}\" style=\"cursor:pointer;margin:2px 0;padding:3px 4px;border:1px solid ${t.border};background:${t.cellBg};border-left:3px solid ${t.accent};border-radius:4px;color:${t.text};\">${esc(it.all_day_event?\"All-day\":hm(it.occurrence_start))} ${esc(it.title||\"\")}<\/div>`).join(\"\");\n    };\n\n    const bindClicks=()=>{\n      Array.from(document.querySelectorAll(\"#cp-view-panel [data-cp-id], #cp-public-list [data-cp-id]\")).forEach(el=>{\n        el.addEventListener(\"click\",async()=>{\n          const id=el.getAttribute(\"data-cp-id\")||\"\";\n          const it=lastItems.find(x=>String(itemId(x))===String(id))||null;\n          if(it){await openEditorForItem(it);}\n        });\n      });\n    };\n    const bindCreateClicks=()=>{\n      Array.from(document.querySelectorAll(\"#cp-view-panel [data-cp-create-date]\")).forEach(el=>{\n        el.addEventListener(\"click\",(ev)=>{\n          if(ev.target && ev.target.closest(\"[data-cp-id]\")){return;}\n          const dateYmd=el.getAttribute(\"data-cp-create-date\")||\"\";\n          if(dateYmd){openEditorCreateAt(dateYmd);}\n        });\n      });\n    };\n\n    const renderView=(items)=>{\n      lastItems=items||[];\n      const view=s(\"cp-view\").value;\n      const panel=s(\"cp-view-panel\");\n      const ul=s(\"cp-public-list\");\n      const title=s(\"cp-events-title\");\n      ul.innerHTML=\"\";\n      if(view===\"list\"){\n        const todayLocal=dmy(new Date());\n        const t=theme();\n        title.textContent=s(\"cp-future-only\").checked?`Events [from ${todayLocal}]`:\"Events\";\n        panel.innerHTML=\"\";\n        (items||[]).slice(0,300).forEach(it=>{\n          const li=document.createElement(\"li\");\n          li.setAttribute(\"data-cp-id\", itemId(it));\n          li.style.cursor=\"pointer\";\n          li.style.background=t.cellBg;\n          li.style.border=`1px solid ${t.border}`;\n          li.style.margin=\"4px 0\";\n          li.style.padding=\"6px 8px\";\n          li.style.borderRadius=\"4px\";\n          const dateLabel=longDate(it.occurrence_start||it.start_datetime);\n          const timeLabel=it.all_day_event?\"All day\":timeRange(it.occurrence_start,it.occurrence_end);\n          const title=it.title||\"\";\n          const desc=String(it.description||\"\").trim();\n          const headline=[dateLabel,timeLabel,title].filter(Boolean).join(\", \");\n          li.innerHTML=`<div>${esc(headline)}<\/div>${(desc!==\"\" && desc!==title)?`<div style=\"color:${t.mutedText};margin-top:2px;\">${esc(desc)}<\/div>`:\"\"}`;\n          ul.appendChild(li);\n        });\n        bindClicks();\n        return;\n      }\n\n      const map={};\n      (items||[]).forEach(it=>{const k=ymd(it.occurrence_start); (map[k]=map[k]||[]).push(it);});\n      const anchor=currentDate();\n      const dow=[\"Sun\",\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\"];\n\n      if(view===\"day\"){\n        const k=s(\"cp-date\").value;\n        title.textContent=`Events for ${dmy(anchor)}`;\n        const day=(map[k]||[]).sort((a,b)=>String(a.occurrence_start).localeCompare(String(b.occurrence_start)));\n        panel.innerHTML=`<div><strong>${esc(k)}<\/strong><\/div><div>${rowsForDay(day)}<\/div>`;\n        bindClicks();\n        return;\n      }\n\n      if(view===\"week\"){\n        const t=theme();\n        const wd=anchor.getDay();\n        const start=new Date(anchor);\n        start.setDate(anchor.getDate()-wd);\n        const end=new Date(start); end.setDate(start.getDate()+6);\n        title.textContent=`Events for ${dmy(start)}\u2013${dmy(end)}`;\n        let cells=\"\";\n        for(let i=0;i<7;i++){\n          const d=new Date(start); d.setDate(start.getDate()+i);\n          const k=localYmd(d);\n          const ev=(map[k]||[]).sort((a,b)=>String(a.occurrence_start).localeCompare(String(b.occurrence_start)));\n          cells+=`<td data-cp-create-date=\"${k}\" style=\"cursor:pointer;vertical-align:top;border:1px solid ${t.border};padding:4px;background:${t.cellBg};\"><div style=\"color:${t.mutedText};\"><strong>${esc(k)}<\/strong><\/div>${rowsForDay(ev)}<\/td>`;\n        }\n        panel.innerHTML=`<table style=\"width:100%;border-collapse:collapse;\"><tr><th style=\"width:65px;border:1px solid ${t.border};background:${t.headBg};\">Time<\/th>${dow.map(n=>`<th style=\"border:1px solid ${t.border};background:${t.headBg};\">${n}<\/th>`).join(\"\")}<\/tr><tr><td style=\"border:1px solid ${t.border};vertical-align:top;padding:4px;background:${t.mutedBg};color:${t.mutedText};\">00:00<br>06:00<br>12:00<br>18:00<\/td>${cells}<\/tr><\/table>`;\n        bindClicks();\n        bindCreateClicks();\n        return;\n      }\n\n      if(view===\"month\"){\n        const t=theme();\n        const first=new Date(anchor.getFullYear(),anchor.getMonth(),1);\n        const start=new Date(first); start.setDate(first.getDate()-first.getDay());\n        title.textContent=`Events for ${monthNames[anchor.getMonth()]}`;\n        const rowParts=[];\n        for(let r=0;r<6;r++){\n          let tds=\"\";\n          let rowHasInMonth=false;\n          for(let c=0;c<7;c++){\n            const i=r*7+c;\n            const d=new Date(start); d.setDate(start.getDate()+i);\n            const k=localYmd(d);\n            const ev=(map[k]||[]).sort((a,b)=>String(a.occurrence_start).localeCompare(String(b.occurrence_start)));\n            const inMonth=d.getMonth()===anchor.getMonth();\n            if(inMonth){rowHasInMonth=true;}\n            tds+=`<td data-cp-create-date=\"${k}\" style=\"cursor:pointer;vertical-align:top;border:1px solid ${t.border};padding:4px;min-height:80px;opacity:${inMonth?1:0.55};background:${inMonth?t.cellBg:t.mutedBg};\"><div style=\"color:${t.mutedText};\"><strong>${esc(k.slice(8,10))}<\/strong><\/div>${rowsForDay(ev.slice(0,6))}<\/td>`;\n          }\n          rowParts.push({html:`<tr>${tds}<\/tr>`,has:rowHasInMonth});\n        }\n        const rows=rowParts.filter(r=>r.has).map(r=>r.html).join(\"\");\n        panel.innerHTML=`<table style=\"width:100%;border-collapse:collapse;\"><tr>${dow.map(n=>`<th style=\"border:1px solid ${t.border};background:${t.headBg};\">${n}<\/th>`).join(\"\")}<\/tr>${rows}<\/table>`;\n        bindClicks();\n        bindCreateClicks();\n        return;\n      }\n\n      if(view===\"year\"){\n        const t=theme();\n        title.textContent=`Events for ${anchor.getFullYear()}`;\n        let out='<div style=\"display:grid;grid-template-columns:repeat(3,minmax(220px,1fr));gap:8px;\">';\n        const mon=[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"];\n        const has=(k)=>Boolean((map[k]||[]).length);\n        for(let m=0;m<12;m++){\n          const first=new Date(anchor.getFullYear(),m,1);\n          const start=new Date(first); start.setDate(first.getDate()-first.getDay());\n          let g=\"\";\n          for(let i=0;i<35;i++){\n            const d=new Date(start); d.setDate(start.getDate()+i);\n            const k=localYmd(d);\n            const same=d.getMonth()===m;\n            g+=`<div data-cp-day=\"${k}\" style=\"cursor:pointer;padding:2px;border:1px solid ${t.border};text-align:center;opacity:${same?1:0.35};font-weight:${has(k)?700:400};background:${same?t.cellBg:t.mutedBg};\">${d.getDate()}<\/div>`;\n          }\n          out+=`<div style=\"border:1px solid ${t.border};padding:4px;background:${t.cellBg};\"><div style=\"color:${t.mutedText};\"><strong>${mon[m]}<\/strong><\/div><div style=\"display:grid;grid-template-columns:repeat(7,1fr);gap:2px;\">${g}<\/div><\/div>`;\n        }\n        out+='<\/div>';\n        panel.innerHTML=out;\n        Array.from(panel.querySelectorAll(\"[data-cp-day]\")).forEach(el=>{\n          el.addEventListener(\"click\",()=>{\n            s(\"cp-date\").value=el.getAttribute(\"data-cp-day\")||s(\"cp-date\").value;\n            s(\"cp-view\").value=\"week\";\n            loadPublic();\n          });\n        });\n        return;\n      }\n    };\n\n    const loadPublic=async()=>{\n      const params={view:s(\"cp-view\").value,date:s(\"cp-date\").value};\n      if(s(\"cp-view\").value===\"list\" && s(\"cp-future-only\").checked){params.future_only=\"1\";}\n      const qs=new URLSearchParams(params);\n      const r=await api(\"\/public\/events?\"+qs.toString());\n      const p=await r.json();\n      if(!r.ok){setStatus((p.error&&p.error.message)||\"Failed to load events\",true); return;}\n      renderView(p.data||[]);\n      futureWrap().style.display=s(\"cp-view\").value===\"list\"?\"flex\":\"none\";\n    };\n\n    s(\"cp-open-login-btn\").onclick=()=>{setAuthStatus(\"\",false); s(\"cp-auth-modal\").style.display=\"flex\";};\n    s(\"cp-close-login-btn\").onclick=()=>{s(\"cp-auth-modal\").style.display=\"none\";};\n    s(\"cp-logout-btn\").onclick=async()=>{\n      await api(\"\/users\/logout\",{method:\"POST\"});\n      auth=null;\n      me=null;\n      setAuthUi();\n      setStatus(\"Logged out\",false);\n    };\n    s(\"cp-create-btn\").onclick=openEditorCreate;\n    s(\"cp-editor-close-btn\").onclick=()=>{s(\"cp-editor-modal\").style.display=\"none\"; setEditorStatus(\"\",false);};\n    s(\"cp-details-close-btn\").onclick=()=>{s(\"cp-details-modal\").style.display=\"none\";};\n\n    s(\"cp-login-btn\").onclick=async()=>{\n      const email=s(\"cp-login-email\").value.trim();\n      const password=s(\"cp-login-password\").value;\n      const r=await api(\"\/users\/login\",{method:\"POST\",headers:{\"Content-Type\":\"application\/json\"},body:JSON.stringify({email,password})});\n      const p=await r.json();\n      if(!r.ok){setAuthStatus(\"Login failure\",true);return;}\n      auth=null;\n      me=(p.data||{}).user||{email};\n      setAuthUi();\n      s(\"cp-auth-modal\").style.display=\"none\";\n      setStatus(\"Logged in\",false);\n    };\n\n    s(\"cp-register-btn\").onclick=async()=>{\n      const email=s(\"cp-login-email\").value.trim();\n      const password=s(\"cp-login-password\").value;\n      const r=await api(\"\/users\/register\",{method:\"POST\",headers:{\"Content-Type\":\"application\/json\"},body:JSON.stringify({email,password})});\n      const p=await r.json();\n      if(!r.ok){setAuthStatus((p.error&&p.error.message)||\"Registration failed\",true);return;}\n      setAuthStatus(\"Registration submitted. Check your email for verification.\",false);\n    };\n\n    s(\"cp-reset-request-btn\").onclick=async()=>{\n      const email=s(\"cp-login-email\").value.trim();\n      const r=await api(\"\/users\/password\/request\",{method:\"POST\",headers:{\"Content-Type\":\"application\/json\"},body:JSON.stringify({email})});\n      const p=await r.json();\n      if(!r.ok){setAuthStatus((p.error&&p.error.message)||\"Reset request failed\",true);return;}\n      setAuthStatus((p.data&&p.data.message)||\"If account exists, reset email sent.\",false);\n    };\n\n    s(\"cp-verify-btn\").onclick=async()=>{\n      const token=s(\"cp-verify-token\").value.trim();\n      if(!token){setAuthStatus(\"Verification token is required\",true);return;}\n      const r=await api(\"\/users\/verify\",{method:\"POST\",headers:{\"Content-Type\":\"application\/json\"},body:JSON.stringify({token})});\n      const p=await r.json();\n      if(!r.ok){setAuthStatus((p.error&&p.error.message)||\"Verification failed\",true);return;}\n      setAuthStatus((p.data&&p.data.message)||\"Email verified. An admin will review your request and notify you if approved.\",false);\n    };\n\n    s(\"cp-editor-create-btn\").onclick=async()=>{\n      if(!me){setEditorStatus(\"Login required\",true);return;}\n      const built=formPayload();\n      if(!built.ok){setEditorStatus(built.message,true); return;}\n      const r=await api(\"\/events\",{method:\"POST\",headers:{\"Content-Type\":\"application\/json\",...authHeaders()},body:JSON.stringify(built.payload)});\n      const p=await r.json();\n      if(!r.ok){setEditorStatus((p.error&&p.error.message)||\"Create failed\",true);return;}\n      s(\"cp-editor-modal\").style.display=\"none\";\n      setEditorStatus(\"\",false);\n      setStatus(\"Event created.\",false);\n      loadPublic();\n    };\n\n    s(\"cp-update-btn\").onclick=async()=>{\n      if(!me){setEditorStatus(\"Login required\",true);return;}\n      const id=s(\"cp-event-id\").value;\n      if(!id){return;}\n      const built=formPayload();\n      if(!built.ok){setEditorStatus(built.message,true); return;}\n      const r=await api(\"\/events\/\"+id,{method:\"PATCH\",headers:{\"Content-Type\":\"application\/json\",...authHeaders()},body:JSON.stringify(built.payload)});\n      const p=await r.json();\n      if(!r.ok){setEditorStatus((p.error&&p.error.message)||\"Update failed\",true);return;}\n      s(\"cp-editor-modal\").style.display=\"none\";\n      setEditorStatus(\"\",false);\n      setStatus(\"Event updated.\",false);\n      loadPublic();\n    };\n\n    s(\"cp-delete-btn\").onclick=async()=>{\n      if(!me){setEditorStatus(\"Login required\",true);return;}\n      const id=s(\"cp-event-id\").value;\n      if(!id){return;}\n      const r=await api(\"\/events\/\"+id,{method:\"DELETE\",headers:authHeaders()});\n      if(!r.ok){const p=await r.json(); setEditorStatus((p.error&&p.error.message)||\"Delete failed\",true);return;}\n      s(\"cp-editor-modal\").style.display=\"none\";\n      setStatus(\"Event deleted.\",false);\n      loadPublic();\n    };\n\n    s(\"cp-delete-occ-confirm-btn\").onclick=async()=>{\n      if(!me){setEditorStatus(\"Login required\",true);return;}\n      const id=s(\"cp-event-id\").value;\n      const key=s(\"cp-occurrence-key-iso\").value.trim();\n      if(!key){setEditorStatus(\"Select an occurrence date first\",true);return;}\n      if(id){\n        const r=await api(\"\/events\/\"+id+\"\/occurrences\/\"+encodeURIComponent(key),{method:\"DELETE\",headers:authHeaders()});\n        if(!r.ok){const p=await r.json(); setEditorStatus((p.error&&p.error.message)||\"Delete occurrence failed\",true);return;}\n        setStatus(\"Occurrence deleted.\",false);\n      } else {\n        if(!pendingDeletedOccurrenceKeys.includes(key)){\n          pendingDeletedOccurrenceKeys.push(key);\n        }\n        setEditorStatus(\"Occurrence removed from preview and will be excluded when saved.\",false);\n      }\n      s(\"cp-occurrence-key-iso\").value=\"\";\n      s(\"cp-occurrence-key\").value=\"\";\n      selectedOccurrenceDate=\"\";\n      await loadOccurrenceChooser();\n      if(id){loadPublic();}\n    };\n\n    s(\"cp-refresh-btn\").onclick=loadPublic;\n    const maybeRefreshOccurrencePreview=()=>{\n      if(s(\"cp-repeat-type\").value!==\"none\"){loadOccurrenceChooser();}\n    };\n    s(\"cp-repeat-type\").onchange=()=>{syncRepeatUi(); maybeRefreshOccurrencePreview(); updateEditorButtons();};\n    s(\"cp-range-mode\").onchange=()=>{syncRepeatUi(); maybeRefreshOccurrencePreview(); updateEditorButtons();};\n    s(\"cp-monthly-nth-mode\").onchange=()=>{syncRepeatUi(); maybeRefreshOccurrencePreview(); updateEditorButtons();};\n    s(\"cp-view\").onchange=loadPublic;\n    s(\"cp-date\").onchange=loadPublic;\n    s(\"cp-future-only\").onchange=loadPublic;\n    s(\"cp-today-btn\").onclick=()=>{setDateInput(new Date()); loadPublic();};\n    s(\"cp-prev-btn\").onclick=()=>stepDate(-1);\n    s(\"cp-next-btn\").onclick=()=>stepDate(1);\n    s(\"cp-occ-prev-btn\").onclick=async()=>{occCursor=new Date(occCursor.getFullYear(),occCursor.getMonth()-1,1); await loadOccurrenceChooser();};\n    s(\"cp-occ-next-btn\").onclick=async()=>{occCursor=new Date(occCursor.getFullYear(),occCursor.getMonth()+1,1); await loadOccurrenceChooser();};\n    s(\"cp-theme\").onchange=()=>{\n      currentThemeName=s(\"cp-theme\").value||\"editorial\";\n      try{localStorage.setItem(themeKey,currentThemeName);}catch(_e){}\n      applyTheme();\n      renderView(lastItems);\n    };\n    s(\"cp-all-day\").onchange=()=>{applyAllDayVisibility(); updateEditorButtons();};\n    s(\"cp-repeat-interval\").addEventListener(\"input\",()=>{s(\"cp-repeat-unit\").textContent=repeatUnitLabel();});\n    s(\"cp-repeat-interval\").addEventListener(\"change\",()=>{s(\"cp-repeat-unit\").textContent=repeatUnitLabel();});\n    [\"cp-title\",\"cp-start-date\",\"cp-end-date\",\"cp-start-time\",\"cp-end-time\",\"cp-repeat-interval\",\"cp-repeat-count\",\"cp-repeat-until\",\"cp-nth-day\",\"cp-nth-pos\",\"cp-nth-weekday\"].forEach(id=>{\n      s(id).addEventListener(\"input\",updateEditorButtons);\n      s(id).addEventListener(\"input\",maybeRefreshOccurrencePreview);\n      s(id).addEventListener(\"change\",updateEditorButtons);\n      s(id).addEventListener(\"change\",maybeRefreshOccurrencePreview);\n    });\n\n    const tokenFromUrl=(new URLSearchParams(window.location.search)).get(\"calendar_verify_token\");\n    if(tokenFromUrl){\n      s(\"cp-verify-token\").value=tokenFromUrl;\n      s(\"cp-auth-modal\").style.display=\"flex\";\n      setAuthStatus(\"Verification token loaded from link. Press Verify Email.\",false);\n    }\n\n    const loadCurrentSession=async()=>{\n      try{\n        const r=await api(\"\/users\/me\");\n        const p=await r.json();\n        if(r.ok){\n          me=(p.data||null);\n          auth=null;\n        } else {\n          me=null;\n        }\n      }catch(_e){\n        me=null;\n      }\n      setAuthUi();\n      updateEditorButtons();\n    };\n\n    try{\n      const savedTheme=localStorage.getItem(themeKey)||\"editorial\";\n      if(themes[savedTheme]){currentThemeName=savedTheme;}\n    }catch(_e){}\n    s(\"cp-theme\").value=currentThemeName;\n    applyTheme();\n    loadCurrentSession().finally(loadPublic);\n  })();<\/script>\n<\/div>\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":4,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"template-full-width.php","meta":{"footnotes":""},"class_list":["post-488","page","type-page","status-publish","hentry"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Willingham Baptist Church Calendar - Willingham Baptist Church<\/title>\n<meta name=\"robots\" content=\"noindex, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Willingham Baptist Church Calendar - Willingham Baptist Church\" \/>\n<meta property=\"og:url\" content=\"https:\/\/willinghambaptist.org\/index.php\/willingham-baptist-church-calendar\/\" \/>\n<meta property=\"og:site_name\" content=\"Willingham Baptist Church\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/facebook.com\/willinghambaptist\" \/>\n<meta property=\"article:modified_time\" content=\"2026-04-01T08:42:03+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data1\" content=\"1 minute\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/willinghambaptist.org\\\/index.php\\\/willingham-baptist-church-calendar\\\/\",\"url\":\"https:\\\/\\\/willinghambaptist.org\\\/index.php\\\/willingham-baptist-church-calendar\\\/\",\"name\":\"Willingham Baptist Church Calendar - Willingham Baptist Church\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/willinghambaptist.org\\\/#website\"},\"datePublished\":\"2026-04-01T08:38:00+00:00\",\"dateModified\":\"2026-04-01T08:42:03+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/willinghambaptist.org\\\/index.php\\\/willingham-baptist-church-calendar\\\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/willinghambaptist.org\\\/index.php\\\/willingham-baptist-church-calendar\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/willinghambaptist.org\\\/index.php\\\/willingham-baptist-church-calendar\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/willinghambaptist.org\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Willingham Baptist Church Calendar\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/willinghambaptist.org\\\/#website\",\"url\":\"https:\\\/\\\/willinghambaptist.org\\\/\",\"name\":\"Willingham Baptist Church\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/willinghambaptist.org\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/willinghambaptist.org\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/willinghambaptist.org\\\/#organization\",\"name\":\"Willingham Baptist Church\",\"url\":\"https:\\\/\\\/willinghambaptist.org\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/willinghambaptist.org\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/willinghambaptist.org\\\/wp-content\\\/uploads\\\/2024\\\/11\\\/cropped-cropped-logo-300x300_bdr-1.jpg\",\"contentUrl\":\"https:\\\/\\\/willinghambaptist.org\\\/wp-content\\\/uploads\\\/2024\\\/11\\\/cropped-cropped-logo-300x300_bdr-1.jpg\",\"width\":150,\"height\":64,\"caption\":\"Willingham Baptist Church\"},\"image\":{\"@id\":\"https:\\\/\\\/willinghambaptist.org\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/facebook.com\\\/willinghambaptist\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Willingham Baptist Church Calendar - Willingham Baptist Church","robots":{"index":"noindex","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"og_locale":"en_GB","og_type":"article","og_title":"Willingham Baptist Church Calendar - Willingham Baptist Church","og_url":"https:\/\/willinghambaptist.org\/index.php\/willingham-baptist-church-calendar\/","og_site_name":"Willingham Baptist Church","article_publisher":"https:\/\/facebook.com\/willinghambaptist","article_modified_time":"2026-04-01T08:42:03+00:00","twitter_card":"summary_large_image","twitter_misc":{"Estimated reading time":"1 minute"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/willinghambaptist.org\/index.php\/willingham-baptist-church-calendar\/","url":"https:\/\/willinghambaptist.org\/index.php\/willingham-baptist-church-calendar\/","name":"Willingham Baptist Church Calendar - Willingham Baptist Church","isPartOf":{"@id":"https:\/\/willinghambaptist.org\/#website"},"datePublished":"2026-04-01T08:38:00+00:00","dateModified":"2026-04-01T08:42:03+00:00","breadcrumb":{"@id":"https:\/\/willinghambaptist.org\/index.php\/willingham-baptist-church-calendar\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/willinghambaptist.org\/index.php\/willingham-baptist-church-calendar\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/willinghambaptist.org\/index.php\/willingham-baptist-church-calendar\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/willinghambaptist.org\/"},{"@type":"ListItem","position":2,"name":"Willingham Baptist Church Calendar"}]},{"@type":"WebSite","@id":"https:\/\/willinghambaptist.org\/#website","url":"https:\/\/willinghambaptist.org\/","name":"Willingham Baptist Church","description":"","publisher":{"@id":"https:\/\/willinghambaptist.org\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/willinghambaptist.org\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Organization","@id":"https:\/\/willinghambaptist.org\/#organization","name":"Willingham Baptist Church","url":"https:\/\/willinghambaptist.org\/","logo":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/willinghambaptist.org\/#\/schema\/logo\/image\/","url":"https:\/\/willinghambaptist.org\/wp-content\/uploads\/2024\/11\/cropped-cropped-logo-300x300_bdr-1.jpg","contentUrl":"https:\/\/willinghambaptist.org\/wp-content\/uploads\/2024\/11\/cropped-cropped-logo-300x300_bdr-1.jpg","width":150,"height":64,"caption":"Willingham Baptist Church"},"image":{"@id":"https:\/\/willinghambaptist.org\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/facebook.com\/willinghambaptist"]}]}},"_links":{"self":[{"href":"https:\/\/willinghambaptist.org\/index.php\/wp-json\/wp\/v2\/pages\/488","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/willinghambaptist.org\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/willinghambaptist.org\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/willinghambaptist.org\/index.php\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/willinghambaptist.org\/index.php\/wp-json\/wp\/v2\/comments?post=488"}],"version-history":[{"count":2,"href":"https:\/\/willinghambaptist.org\/index.php\/wp-json\/wp\/v2\/pages\/488\/revisions"}],"predecessor-version":[{"id":490,"href":"https:\/\/willinghambaptist.org\/index.php\/wp-json\/wp\/v2\/pages\/488\/revisions\/490"}],"wp:attachment":[{"href":"https:\/\/willinghambaptist.org\/index.php\/wp-json\/wp\/v2\/media?parent=488"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}