PagesStructures['id1790341329143'] = {"structures":[{"type":"page","id":"id1790341329143","elementProperties":{"tagName":"DIV","behaviours":null,"isLocked":false,"name":"Testing","baseName":"SettingUp","templateID":null,"templateName":null,"order":0,"customStates":null,"isElementWasEditedInMode":true,"showHoverEffects":true,"skinInformation":{"categoryId":245},"isSupportsMobile":false,"isVisibleInMode":true,"isFixed":false,"topZIndex":0,"elementOpacity":1,"staticMargin":{"horizontalMargin":0,"verticalMargin":0},"sizeAndPosition":{"width":0,"height":1068,"top":0,"left":0},"lastResizingSize":{"width":0,"height":1068,"top":0,"left":0},"isVisibleInLastSection":true,"isVisibleInLastDataItem":true,"attributes":null,"metaProps":null,"metaItemType":null,"metaTitle":null,"styleBindingId":null,"styleBindingFields":null,"shadow":{"top":0,"left":0,"spread":0,"blur":0,"color":"black"},"glow":{"spread":0,"blur":0,"color":"black"},"isParallaxBackground":false,"parallaxBackgroundSpeed":0.5,"isParallaxElement":{"isActive":false,"speed":1,"delay":0},"effectsOptions":{"isParallax":false,"oneTimeAnimation":false,"duration":1200,"startDistance":200,"startVisibility":0.8,"distance":300,"measureDistanceType":3,"delay":0,"distanceDelay":0,"runInLoop":false,"flyDirection":2,"direction":"horizontal","movementDistanceHorizontally":200,"movementDistanceVertically":0,"autoStartDistanceSettings":true,"autoDistanceSettings":true},"effects":null,"binding":null,"verticalAlign":"center","horizontalAlign":"center","horizontalContentAlign":"center","basicUserCanEdit":true,"overflow":false,"isGrowable":{"bottom":false,"right":false},"rowsItems":null,"childrenAnchor":"center","backgroundColor":"#fff","imageUrl":"","imageLayout":"repeat","imagePosition":{"horizontal":"center","vertical":"top"},"origImage":"","imageOpacity":0.26,"backgroundOverlay":"transparent","gridLines":[],"fixedBackground":true,"statesGroups":null},"metaData":{"position":{"left":-1079.4921875,"top":0},"size":{"width":2159,"height":3457}},"childElements":[{"type":"SectionElement","id":"id1790341329144","elementProperties":{"tagName":"SECTION","behaviours":null,"isLocked":false,"name":"Section 2","baseName":null,"templateID":null,"templateName":null,"order":3,"customStates":null,"isElementWasEditedInMode":false,"showHoverEffects":true,"skinInformation":{},"isSupportsMobile":false,"isVisibleInMode":true,"isFixed":false,"topZIndex":0,"elementOpacity":1,"staticMargin":{"horizontalMargin":0,"verticalMargin":0},"sizeAndPosition":{"height":2796,"left":0,"width":2159,"top":0},"lastResizingSize":{"width":2159,"height":2796},"isVisibleInLastSection":true,"isVisibleInLastDataItem":true,"attributes":null,"metaProps":null,"metaItemType":null,"metaTitle":null,"styleBindingId":null,"styleBindingFields":null,"shadow":{"top":0,"left":0,"spread":0,"blur":0,"color":"black"},"glow":{"spread":0,"blur":0,"color":"black"},"isParallaxBackground":false,"parallaxBackgroundSpeed":0.5,"isParallaxElement":{"isActive":false,"speed":1,"delay":0},"effectsOptions":{"isParallax":false,"oneTimeAnimation":false,"duration":1200,"startDistance":200,"startVisibility":0.8,"distance":300,"measureDistanceType":3,"delay":0,"distanceDelay":0,"runInLoop":false,"flyDirection":2,"direction":"horizontal","movementDistanceHorizontally":200,"movementDistanceVertically":0,"autoStartDistanceSettings":true,"autoDistanceSettings":true},"effects":null,"binding":null,"innerGlow":{"spread":0,"blur":0,"color":"black"},"innerShadow":{"top":0,"left":0,"spread":0,"blur":0,"color":"black"},"padding":{"top":0,"left":0,"bottom":0,"right":0},"basicUserCanEdit":true,"backgroundColor":"transparent","imageUrl":"","imageLayout":"stretchedToFill","imagePosition":{"vertical":"center","horizontal":"center"},"origImage":"","imageOpacity":1,"backgroundOverlay":"transparent","verticalLayout":"normal","horizontalLayout":"normal","fillLayout":{"fillVertical":false,"fillHorizontal":false},"margin":{"top":0,"left":0,"bottom":0,"right":0},"overflow":false,"isGrowable":{"bottom":false,"right":false},"rowsItems":null,"childrenAnchor":"center","resizingGripPosiotion":"s","sectionName":"Section A","pageContentType":1,"borderWidth":{"top":0,"left":0,"bottom":0,"right":0},"roundness":{"topLeft":0,"bottomLeft":0,"topRight":0,"bottomRight":0},"borderColor":{"top":"Black","left":"Black","bottom":"Black","right":"Black"},"borderStyle":{"top":"solid","left":"solid","bottom":"solid","right":"solid"}},"metaData":{"position":{"left":-1079.4921875,"top":160},"size":{"width":2159,"height":2796}},"childElements":[{"type":"ExternalAppembed_html_app1","id":"id1790341340590","elementProperties":{"tagName":"DIV","behaviours":null,"isLocked":false,"name":"Embed Html 7","baseName":null,"templateID":"templateid1790341340591","templateName":null,"order":83,"customStates":null,"isElementWasEditedInMode":false,"showHoverEffects":true,"skinInformation":{},"isSupportsMobile":false,"isVisibleInMode":true,"isFixed":false,"topZIndex":0,"elementOpacity":1,"staticMargin":{"horizontalMargin":0,"verticalMargin":0},"sizeAndPosition":{"width":1136,"height":2404,"left":-562,"top":0},"lastResizingSize":{"width":1136,"height":2404},"isVisibleInLastSection":true,"isVisibleInLastDataItem":true,"attributes":null,"metaProps":null,"metaItemType":null,"metaTitle":null,"styleBindingId":null,"styleBindingFields":null,"shadow":{"top":0,"left":0,"spread":0,"blur":0,"color":"black"},"glow":{"spread":0,"blur":0,"color":"black"},"isParallaxBackground":false,"parallaxBackgroundSpeed":0.5,"isParallaxElement":{"isActive":false,"speed":1,"delay":0},"effectsOptions":{"isParallax":false,"oneTimeAnimation":false,"duration":1200,"startDistance":200,"startVisibility":0.8,"distance":300,"measureDistanceType":3,"delay":0,"distanceDelay":0,"runInLoop":false,"flyDirection":2,"direction":"horizontal","movementDistanceHorizontally":200,"movementDistanceVertically":0,"autoStartDistanceSettings":true,"autoDistanceSettings":true},"effects":null,"binding":null,"innerGlow":{"spread":0,"blur":0,"color":"black"},"innerShadow":{"top":0,"left":0,"spread":0,"blur":0,"color":"black"},"basicUserCanEdit":true,"backgroundColor":"transparent","padding":{"top":0,"left":0,"bottom":0,"right":0},"imageUrl":"","imageLayout":"stretchedToFill","imagePosition":{"vertical":"center","horizontal":"center"},"origImage":"","imageOpacity":1,"backgroundOverlay":"transparent","verticalLayout":"normal","horizontalLayout":"normal","fillLayout":{"fillHorizontal":false,"fillVertical":false},"margin":{"top":0,"left":0,"bottom":0,"right":0},"isVisible":true,"borderWidth":{"top":0,"left":0,"bottom":0,"right":0},"roundness":{"topLeft":0,"bottomLeft":0,"topRight":0,"bottomRight":0},"borderColor":{"top":"Black","left":"Black","bottom":"Black","right":"Black"},"borderStyle":{"top":"solid","left":"solid","bottom":"solid","right":"solid"},"rotationAngle":0,"display":"fixed","cellItem":null,"cellHorizontalAlignment":"none","verticalAlign":"center","horizontalAlign":"center","horizontalContentAlign":"center","embed_html_app1html":"<!doctype html>\n<html lang=\"en-GB\">\n<head>\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n\n<title>What's On in Swale | Swale CVS</title>\n\n<link rel=\"stylesheet\" href=\"https://unpkg.com/leaflet@1.9.4/dist/leaflet.css\">\n<link rel=\"stylesheet\" href=\"https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.css\">\n<link rel=\"stylesheet\" href=\"https://unpkg.com/leaflet.markercluster@1.5.3/dist/MarkerCluster.Default.css\">\n\n<style>\n:root{\n  --navy:#07366d;\n  --blue:#0b57c9;\n  --cyan:#17b8cf;\n  --orange:#ff7a1a;\n  --ink:#10213a;\n  --muted:#607086;\n  --white:#ffffff;\n  --line:#dbe4ee;\n  --soft:#f6f9fc;\n  --shadow:0 7px 20px rgba(4,35,80,.07);\n}\n\n*{box-sizing:border-box}\n\nhtml{\n  scroll-behavior:smooth;\n  background:transparent;\n}\n\nbody{\n  margin:0;\n  padding:0;\n  font-family:Inter,system-ui,-apple-system,\"Segoe UI\",Roboto,Arial,sans-serif;\n  color:var(--ink);\n  background:transparent;\n  line-height:1.5;\n}\n\nbutton,input,select,textarea{\n  font:inherit;\n}\n\nbutton{\n  cursor:pointer;\n}\n\na{\n  color:var(--blue);\n}\n\n.shell{\n  width:100%;\n  max-width:1180px;\n  margin:0 auto;\n  padding-left:22px;\n  padding-right:22px;\n}\n\n.primary{\n  border:0;\n  border-radius:10px;\n  background:var(--blue);\n  color:#fff;\n  padding:12px 18px;\n  font-weight:800;\n  transition:.15s ease;\n}\n\n.primary:hover{\n  background:#084aa9;\n}\n\n.secondary{\n  border:1px solid #c9d8e8;\n  border-radius:10px;\n  background:#fff;\n  color:var(--navy);\n  padding:11px 16px;\n  font-weight:800;\n  transition:.15s ease;\n}\n\n.secondary:hover{\n  border-color:#8fb1d4;\n  background:#f8fbfe;\n}\n\n\n/* =========================================================\n   INTRO\n   Designed to sit naturally beneath the Swale CVS header\n   ========================================================= */\n\n.hero{\n  position:relative;\n  background:transparent;\n  padding:34px 0 26px;\n}\n\n.hero:before{\n  content:\"\";\n  display:block;\n  width:58px;\n  height:3px;\n  border-radius:10px;\n  margin:0 0 24px 22px;\n  background:linear-gradient(\n    90deg,\n    var(--cyan) 0 60%,\n    var(--orange) 60% 100%\n  );\n}\n\n.hero-inner{\n  display:block;\n}\n\n.eyebrow{\n  display:block;\n  margin-bottom:8px;\n  font-size:12px;\n  font-weight:900;\n  letter-spacing:.14em;\n  text-transform:uppercase;\n  color:var(--blue);\n}\n\n.hero-copy{\n  max-width:800px;\n}\n\n.hero-copy h1{\n  margin:0 0 12px;\n  color:var(--navy);\n  font-size:clamp(38px,5vw,58px);\n  line-height:1.02;\n  letter-spacing:-.045em;\n}\n\n.hero-copy p{\n  max-width:690px;\n  margin:0 0 12px;\n  color:var(--muted);\n  font-size:17px;\n  line-height:1.65;\n}\n\n.hero-count{\n  margin-top:8px;\n}\n\n.hero-count strong{\n  color:var(--navy);\n  font-size:14px;\n}\n\n\n/* =========================================================\n   SEARCH\n   No floating app-style panel\n   ========================================================= */\n\n.directory-search{\n  padding:8px 0 32px;\n  background:transparent;\n}\n\n.search-panel{\n  max-width:none;\n}\n\n.searchbox{\n  display:flex;\n  gap:8px;\n  width:100%;\n  background:#fff;\n  border:1px solid #cbd9e8;\n  border-radius:12px;\n  padding:7px;\n  box-shadow:0 4px 14px rgba(4,35,80,.045);\n}\n\n.searchbox input{\n  flex:1;\n  min-width:0;\n  border:0;\n  outline:0;\n  background:transparent;\n  padding:11px 13px;\n  font-size:15px;\n  color:var(--ink);\n}\n\n.searchbox input::placeholder{\n  color:#7b8999;\n}\n\n.filters{\n  display:grid;\n  grid-template-columns:repeat(3,1fr);\n  gap:12px;\n  margin-top:12px;\n}\n\n.field label{\n  display:block;\n  margin:0 0 5px;\n  color:var(--navy);\n  font-size:11px;\n  font-weight:900;\n  letter-spacing:.04em;\n}\n\n.field select{\n  width:100%;\n  border:1px solid #cbd9e8;\n  border-radius:10px;\n  background:#fff;\n  color:var(--ink);\n  padding:11px 12px;\n}\n\n.quick-actions{\n  display:flex;\n  gap:10px;\n  align-items:center;\n  flex-wrap:wrap;\n  margin-top:14px;\n}\n\n.map-button{\n  display:inline-flex;\n  align-items:center;\n  justify-content:center;\n  gap:8px;\n}\n\n.button-icon{\n  width:17px;\n  height:17px;\n  fill:none;\n  stroke:currentColor;\n  stroke-width:1.8;\n  stroke-linecap:round;\n  stroke-linejoin:round;\n}\n\n\n/* =========================================================\n   INTERESTS\n   ========================================================= */\n\n.categories{\n  padding:30px 0 24px;\n  border-top:1px solid #edf1f5;\n}\n\n.section-label{\n  display:block;\n  margin-bottom:5px;\n  color:var(--blue);\n  font-size:11px;\n  font-weight:900;\n  letter-spacing:.13em;\n  text-transform:uppercase;\n}\n\n.categories h2,\n.results h2{\n  margin:0 0 5px;\n  color:var(--navy);\n  font-size:clamp(27px,3.4vw,38px);\n  line-height:1.1;\n  letter-spacing:-.035em;\n}\n\n.categories > .shell > p{\n  margin:0 0 18px;\n  color:var(--muted);\n}\n\n.cat-grid{\n  display:grid;\n  grid-template-columns:repeat(5,1fr);\n  gap:12px;\n}\n\n.cat{\n  min-height:154px;\n  padding:16px 14px;\n  border:1px solid var(--line);\n  border-radius:14px;\n  background:#fff;\n  color:var(--navy);\n  text-align:left;\n  box-shadow:0 4px 12px rgba(4,35,80,.045);\n  transition:\n    transform .15s ease,\n    box-shadow .15s ease,\n    border-color .15s ease;\n}\n\n.cat:hover{\n  transform:translateY(-2px);\n  border-color:#a9c5e1;\n  box-shadow:0 8px 18px rgba(4,35,80,.08);\n}\n\n.cat.active{\n  border-color:var(--blue);\n  box-shadow:0 0 0 2px rgba(11,87,201,.12);\n}\n\n.cat-icon{\n  display:grid;\n  place-items:center;\n  width:36px;\n  height:36px;\n  margin-bottom:11px;\n  border-radius:10px;\n  font-size:19px;\n}\n\n.cat-social .cat-icon{\n  background:#e8f2ff;\n}\n\n.cat-sports .cat-icon{\n  background:#e2f7f0;\n}\n\n.cat-arts .cat-icon{\n  background:#f0e9fc;\n}\n\n.cat-skills .cat-icon{\n  background:#fff0df;\n}\n\n.cat-other .cat-icon{\n  background:#edf0f4;\n}\n\n.cat strong{\n  display:block;\n  margin-bottom:6px;\n  color:var(--navy);\n  font-size:14px;\n  line-height:1.25;\n}\n\n.cat small{\n  display:block;\n  color:#607086;\n  font-size:12px;\n  line-height:1.45;\n  font-weight:500;\n}\n\n\n/* =========================================================\n   RESULTS\n   ========================================================= */\n\n.results{\n  padding:28px 0 42px;\n  border-top:1px solid #edf1f5;\n}\n\n.results-head{\n  display:flex;\n  justify-content:space-between;\n  align-items:flex-end;\n  gap:20px;\n  margin-bottom:18px;\n}\n\n.results-head h2{\n  font-size:30px;\n}\n\n.results-head p{\n  margin:4px 0 0;\n  color:var(--muted);\n}\n\n.actions{\n  display:flex;\n  gap:8px;\n  flex-wrap:wrap;\n}\n\n.toggle.active{\n  background:var(--navy);\n  color:#fff;\n  border-color:var(--navy);\n}\n\n.loading{\n  padding:18px 0;\n  color:var(--navy);\n  font-weight:800;\n}\n\n.cards{\n  display:grid;\n  grid-template-columns:repeat(3,1fr);\n  gap:15px;\n}\n\n.card{\n  position:relative;\n  display:flex;\n  flex-direction:column;\n  gap:10px;\n  overflow:hidden;\n  padding:18px;\n  border:1px solid var(--line);\n  border-top-width:4px;\n  border-radius:15px;\n  box-shadow:0 5px 16px rgba(4,35,80,.055);\n}\n\n\n/* Activity category colours */\n\n.card.cat-social{\n  background:#f5f9ff;\n  border-top-color:#2f74d0;\n}\n\n.card.cat-sports{\n  background:#f2fbf8;\n  border-top-color:#18a887;\n}\n\n.card.cat-arts{\n  background:#faf6ff;\n  border-top-color:#8157cf;\n}\n\n.card.cat-skills{\n  background:#fff8f1;\n  border-top-color:#ef7b2d;\n}\n\n.card.cat-other{\n  background:#f7f8fa;\n  border-top-color:#7a8797;\n}\n\n.pill{\n  display:inline-flex;\n  align-self:flex-start;\n  padding:5px 9px;\n  border-radius:999px;\n  font-size:11px;\n  font-weight:850;\n}\n\n.cat-social .pill{\n  background:#e5f0ff;\n  color:#174f98;\n}\n\n.cat-sports .pill{\n  background:#dff6ef;\n  color:#0d725d;\n}\n\n.cat-arts .pill{\n  background:#eee5fb;\n  color:#6239a7;\n}\n\n.cat-skills .pill{\n  background:#ffead7;\n  color:#a84d12;\n}\n\n.cat-other .pill{\n  background:#e9edf2;\n  color:#4e5d6d;\n}\n\n.card h3{\n  margin:0;\n  color:var(--navy);\n  font-size:19px;\n  line-height:1.2;\n}\n\n.org{\n  color:#3e536c;\n  font-weight:750;\n}\n\n.meta{\n  color:#52657c;\n  font-size:14px;\n}\n\n.desc{\n  display:-webkit-box;\n  overflow:hidden;\n  color:#43566d;\n  font-size:14px;\n  -webkit-line-clamp:3;\n  -webkit-box-orient:vertical;\n}\n\n.card-actions{\n  display:flex;\n  gap:8px;\n  flex-wrap:wrap;\n  margin-top:auto;\n  padding-top:5px;\n}\n\n.card-actions button,\n.card-actions a{\n  font-size:13px;\n  text-decoration:none;\n}\n\n\n/* =========================================================\n   MAP\n   ========================================================= */\n\n#map{\n  width:100%;\n  height:480px;\n  border:1px solid var(--line);\n  border-radius:15px;\n  background:#dce9ed;\n  box-shadow:var(--shadow);\n}\n\n.marker{\n  width:32px;\n  height:32px;\n  border:4px solid #fff;\n  border-radius:50% 50% 50% 8px;\n  background:var(--blue);\n  box-shadow:0 5px 12px rgba(4,35,80,.3);\n  transform:rotate(-45deg);\n}\n\n.cluster{\n  display:grid;\n  place-items:center;\n  width:42px;\n  height:42px;\n  border:4px solid #fff;\n  border-radius:50%;\n  background:var(--navy);\n  color:#fff;\n  font-weight:900;\n}\n\n\n/* =========================================================\n   PAGINATION\n   ========================================================= */\n\n.pagination{\n  display:flex;\n  justify-content:center;\n  align-items:center;\n  gap:10px;\n  margin-top:22px;\n}\n\n.pagination button{\n  padding:8px 14px;\n  border:1px solid var(--line);\n  border-radius:999px;\n  background:#fff;\n  color:var(--navy);\n  font-weight:700;\n}\n\n.pagination button:disabled{\n  opacity:.45;\n}\n\n.empty{\n  grid-column:1/-1;\n  padding:30px;\n  border:1px solid var(--line);\n  border-radius:15px;\n  background:#fafcfe;\n  color:var(--muted);\n  text-align:center;\n}\n\n\n/* =========================================================\n   LIST AN ACTIVITY\n   ========================================================= */\n\n.submit-strip{\n  display:flex;\n  justify-content:space-between;\n  align-items:center;\n  gap:20px;\n  margin-top:36px;\n  padding:22px 0 0;\n  border-top:1px solid #e4eaf0;\n}\n\n.submit-strip h3{\n  margin:0 0 4px;\n  color:var(--navy);\n}\n\n.submit-strip p{\n  margin:0;\n  color:var(--muted);\n}\n\n\n/* =========================================================\n   MODALS\n   ========================================================= */\n\n.modal-bg{\n  position:fixed;\n  inset:0;\n  z-index:2000;\n  display:none;\n  align-items:flex-start;\n  justify-content:center;\n  overflow:auto;\n  padding:24px;\n  background:rgba(3,22,48,.65);\n}\n\n.modal-bg.open{\n  display:flex;\n}\n\n.modal{\n  width:min(760px,100%);\n  overflow:hidden;\n  border-radius:18px;\n  background:#fff;\n  box-shadow:0 25px 80px rgba(0,0,0,.3);\n}\n\n.modal-head{\n  position:sticky;\n  top:0;\n  z-index:2;\n  display:flex;\n  justify-content:space-between;\n  align-items:center;\n  padding:16px 20px;\n  border-bottom:1px solid var(--line);\n  background:#fff;\n}\n\n.modal-head h2{\n  margin:0;\n  color:var(--navy);\n}\n\n.close{\n  padding:7px 10px;\n  border:1px solid var(--line);\n  border-radius:9px;\n  background:#fff;\n}\n\n.modal-body{\n  padding:20px;\n}\n\n.form-grid{\n  display:grid;\n  grid-template-columns:1fr 1fr;\n  gap:14px;\n}\n\n.form-grid .wide{\n  grid-column:1/-1;\n}\n\n.form-grid label{\n  display:block;\n  margin-bottom:5px;\n  font-size:13px;\n  font-weight:800;\n}\n\n.form-grid input,\n.form-grid select,\n.form-grid textarea{\n  width:100%;\n  padding:11px;\n  border:1px solid var(--line);\n  border-radius:10px;\n  background:#fff;\n}\n\n.form-grid textarea{\n  min-height:105px;\n  resize:vertical;\n}\n\n.note{\n  color:var(--muted);\n  font-size:12px;\n}\n\n.form-actions{\n  display:flex;\n  justify-content:flex-end;\n  gap:10px;\n  margin-top:18px;\n}\n\n.success{\n  display:none;\n  margin-bottom:14px;\n  padding:12px;\n  border-radius:10px;\n  background:#ecfdf3;\n  color:#166534;\n  font-weight:800;\n}\n\n.detail .modal-body{\n  display:grid;\n  gap:12px;\n}\n\n.detail-title{\n  margin:0;\n  color:var(--navy);\n  font-size:28px;\n}\n\n.detail-desc{\n  white-space:pre-wrap;\n}\n\n.detail-actions{\n  display:flex;\n  gap:8px;\n  flex-wrap:wrap;\n}\n\n.hidden{\n  display:none!important;\n}\n\n\n/* =========================================================\n   MOBILE\n   ========================================================= */\n\n@media(max-width:900px){\n\n  .cat-grid{\n    grid-template-columns:repeat(2,1fr);\n  }\n\n  .cards{\n    grid-template-columns:repeat(2,1fr);\n  }\n}\n\n@media(max-width:650px){\n\n  .shell{\n    padding-left:14px;\n    padding-right:14px;\n  }\n\n  .hero{\n    padding-top:24px;\n  }\n\n  .hero:before{\n    margin-left:14px;\n  }\n\n  .hero-copy h1{\n    font-size:40px;\n  }\n\n  .hero-copy p{\n    font-size:15px;\n  }\n\n  .searchbox{\n    display:grid;\n  }\n\n  .filters{\n    grid-template-columns:1fr;\n  }\n\n  .quick-actions{\n    display:grid;\n    grid-template-columns:1fr 1fr;\n  }\n\n  .quick-actions button{\n    width:100%;\n  }\n\n  .cat-grid{\n    grid-template-columns:1fr;\n  }\n\n  .cat{\n    min-height:auto;\n  }\n\n  .cards{\n    grid-template-columns:1fr;\n  }\n\n  .results-head{\n    align-items:flex-start;\n    flex-direction:column;\n  }\n\n  .submit-strip{\n    align-items:flex-start;\n    flex-direction:column;\n  }\n\n  .form-grid{\n    grid-template-columns:1fr;\n  }\n\n  .form-grid .wide{\n    grid-column:auto;\n  }\n\n  #map{\n    height:62vh;\n    min-height:390px;\n  }\n}\n</style>\n</head>\n\n<body>\n\n\n<!-- ======================================================\n     INTRODUCTION\n     ====================================================== -->\n\n<section class=\"hero\">\n\n  <div class=\"shell hero-inner\">\n\n    <div class=\"hero-copy\">\n\n      <span class=\"eyebrow\">\n        Explore activities across Swale\n      </span>\n\n      <h1>\n        Find local activities.\n      </h1>\n\n      <p>\n        From social groups and wellbeing sessions to arts,\n        culture and learning, find something that feels right for you.\n      </p>\n\n      <div class=\"hero-count\">\n        <strong id=\"heroCount\">\n          Loading activities…\n        </strong>\n      </div>\n\n    </div>\n\n  </div>\n\n</section>\n\n\n<!-- ======================================================\n     SEARCH\n     ====================================================== -->\n\n<section class=\"directory-search\">\n\n  <div class=\"shell\">\n\n    <div class=\"search-panel\">\n\n      <div class=\"searchbox\">\n\n        <input\n          id=\"q\"\n          type=\"search\"\n          aria-label=\"Search activities\"\n          placeholder=\"Search activities, groups or locations...\"\n        >\n\n        <button\n          class=\"primary\"\n          id=\"searchBtn\"\n        >\n          Search\n        </button>\n\n      </div>\n\n\n      <div class=\"filters\">\n\n        <div class=\"field\">\n\n          <label for=\"area\">\n            AREA\n          </label>\n\n          <select id=\"area\">\n\n            <option value=\"\">\n              All of Swale\n            </option>\n\n            <option>\n              Sittingbourne\n            </option>\n\n            <option>\n              Sheppey\n            </option>\n\n            <option>\n              Faversham\n            </option>\n\n            <option>\n              Wider Swale\n            </option>\n\n          </select>\n\n        </div>\n\n\n        <div class=\"field\">\n\n          <label for=\"age\">\n            WHO FOR?\n          </label>\n\n          <select id=\"age\">\n\n            <option value=\"\">\n              Everyone\n            </option>\n\n            <option>\n              Children\n            </option>\n\n            <option>\n              Young people\n            </option>\n\n            <option>\n              Adults\n            </option>\n\n            <option>\n              Older people\n            </option>\n\n          </select>\n\n        </div>\n\n\n        <div class=\"field\">\n\n          <label for=\"when\">\n            WHEN?\n          </label>\n\n          <select id=\"when\">\n\n            <option value=\"\">\n              Any time\n            </option>\n\n            <option value=\"today\">\n              Today\n            </option>\n\n            <option value=\"week\">\n              This week\n            </option>\n\n            <option value=\"oneoff\">\n              One-off events\n            </option>\n\n            <option value=\"ongoing\">\n              Regular / ongoing\n            </option>\n\n          </select>\n\n        </div>\n\n      </div>\n\n\n      <div class=\"quick-actions\">\n\n        <button\n          class=\"primary\"\n          id=\"browseBtn\"\n        >\n          Browse all activities ↓\n        </button>\n\n\n        <button\n          class=\"secondary map-button\"\n          id=\"heroMapBtn\"\n        >\n\n          <svg\n            class=\"button-icon\"\n            viewBox=\"0 0 24 24\"\n            aria-hidden=\"true\"\n          >\n\n            <circle\n              cx=\"12\"\n              cy=\"12\"\n              r=\"9\"\n            ></circle>\n\n            <path d=\"M3 12h18\"></path>\n\n            <path\n              d=\"M12 3c2.4 2.5 3.7 5.5 3.7 9S14.4 18.5 12 21\"\n            ></path>\n\n            <path\n              d=\"M12 3C9.6 5.5 8.3 8.5 8.3 12S9.6 18.5 12 21\"\n            ></path>\n\n          </svg>\n\n          <span>\n            View map\n          </span>\n\n        </button>\n\n      </div>\n\n    </div>\n\n  </div>\n\n</section>\n\n\n<!-- ======================================================\n     BROWSE BY INTEREST\n     ====================================================== -->\n\n<section class=\"categories\">\n\n  <div class=\"shell\">\n\n    <span class=\"section-label\">\n      Browse by interest\n    </span>\n\n    <h2>\n      Activities for every interest\n    </h2>\n\n    <p>\n      Choose an interest to explore what's happening across Swale.\n    </p>\n\n\n    <div\n      class=\"cat-grid\"\n      id=\"categories\"\n    >\n\n\n      <button\n        class=\"cat cat-social\"\n        data-cat=\"Social / Befriending\"\n      >\n\n        <span class=\"cat-icon\">\n          ☕\n        </span>\n\n        <strong>\n          Social / Befriending\n        </strong>\n\n        <small>\n          Looking for a coffee morning, social group\n          or somewhere to meet new people?\n        </small>\n\n      </button>\n\n\n      <button\n        class=\"cat cat-sports\"\n        data-cat=\"Sports / Wellbeing\"\n      >\n\n        <span class=\"cat-icon\">\n          🏃\n        </span>\n\n        <strong>\n          Sports / Wellbeing\n        </strong>\n\n        <small>\n          Want to get active, improve your wellbeing\n          or find something that helps you feel good?\n        </small>\n\n      </button>\n\n\n      <button\n        class=\"cat cat-arts\"\n        data-cat=\"Arts / Culture\"\n      >\n\n        <span class=\"cat-icon\">\n          🎨\n        </span>\n\n        <strong>\n          Arts / Culture\n        </strong>\n\n        <small>\n          Interested in crafts, music, creative activities\n          or local cultural groups and events?\n        </small>\n\n      </button>\n\n\n      <button\n        class=\"cat cat-skills\"\n        data-cat=\"Skills / Volunteering\"\n      >\n\n        <span class=\"cat-icon\">\n          💡\n        </span>\n\n        <strong>\n          Skills / Volunteering\n        </strong>\n\n        <small>\n          Want to learn something new, build your skills\n          or give some of your time to help others?\n        </small>\n\n      </button>\n\n\n      <button\n        class=\"cat cat-other\"\n        data-cat=\"Other\"\n      >\n\n        <span class=\"cat-icon\">\n          🤝\n        </span>\n\n        <strong>\n          Other\n        </strong>\n\n        <small>\n          Looking for something different?\n          Explore more activities, groups and opportunities across Swale.\n        </small>\n\n      </button>\n\n\n    </div>\n\n  </div>\n\n</section>\n\n\n<!-- ======================================================\n     RESULTS\n     ====================================================== -->\n\n<section class=\"results\">\n\n  <div class=\"shell\">\n\n\n    <div class=\"results-head\">\n\n      <div>\n\n        <span class=\"section-label\">\n          Explore the directory\n        </span>\n\n        <h2>\n          What's happening?\n        </h2>\n\n        <p id=\"count\">\n          Loading activities…\n        </p>\n\n      </div>\n\n\n      <div class=\"actions\">\n\n        <button\n          class=\"secondary toggle active\"\n          id=\"listBtn\"\n        >\n          List view\n        </button>\n\n        <button\n          class=\"secondary toggle\"\n          id=\"mapBtn\"\n        >\n          Map view\n        </button>\n\n        <button\n          class=\"secondary\"\n          id=\"clearBtn\"\n        >\n          Clear filters\n        </button>\n\n      </div>\n\n    </div>\n\n\n    <div\n      class=\"loading\"\n      id=\"loading\"\n    >\n      Fetching activities…\n    </div>\n\n\n    <div\n      class=\"cards hidden\"\n      id=\"listView\"\n    ></div>\n\n\n    <div\n      class=\"pagination\"\n      id=\"pagination\"\n    ></div>\n\n\n    <div\n      class=\"hidden\"\n      id=\"mapView\"\n    >\n\n      <div id=\"map\"></div>\n\n    </div>\n\n\n    <div class=\"submit-strip\">\n\n      <div>\n\n        <h3>\n          Run an activity or community group?\n        </h3>\n\n        <p>\n          Add it to the Swale CVS What's On directory.\n        </p>\n\n      </div>\n\n\n      <button\n        class=\"secondary\"\n        id=\"openSubmit\"\n      >\n        List an activity\n      </button>\n\n    </div>\n\n\n  </div>\n\n</section>\n\n\n<!-- ======================================================\n     ACTIVITY DETAILS\n     ====================================================== -->\n\n<div\n  class=\"modal-bg\"\n  id=\"detailModal\"\n  aria-hidden=\"true\"\n>\n\n  <div class=\"modal detail\">\n\n    <div class=\"modal-head\">\n\n      <h2>\n        Activity details\n      </h2>\n\n      <button\n        class=\"close\"\n        data-close=\"detailModal\"\n      >\n        Close\n      </button>\n\n    </div>\n\n\n    <div\n      class=\"modal-body\"\n      id=\"detailBody\"\n    ></div>\n\n  </div>\n\n</div>\n\n\n<!-- ======================================================\n     SUBMIT ACTIVITY\n     ====================================================== -->\n\n<div\n  class=\"modal-bg\"\n  id=\"submitModal\"\n  aria-hidden=\"true\"\n>\n\n  <div class=\"modal\">\n\n\n    <div class=\"modal-head\">\n\n      <h2>\n        List an activity\n      </h2>\n\n      <button\n        class=\"close\"\n        data-close=\"submitModal\"\n      >\n        Close\n      </button>\n\n    </div>\n\n\n    <div class=\"modal-body\">\n\n\n      <div\n        class=\"success\"\n        id=\"success\"\n      >\n        Thank you. Your activity has been submitted.\n      </div>\n\n\n      <form id=\"activityForm\">\n\n\n        <div class=\"form-grid\">\n\n\n          <div>\n\n            <label>\n              Activity name *\n            </label>\n\n            <input\n              name=\"title\"\n              required\n            >\n\n          </div>\n\n\n          <div>\n\n            <label>\n              Organisation *\n            </label>\n\n            <input\n              name=\"organisation\"\n              required\n            >\n\n          </div>\n\n\n          <div class=\"wide\">\n\n            <label>\n              Description *\n            </label>\n\n            <textarea\n              name=\"description\"\n              required\n            ></textarea>\n\n          </div>\n\n\n          <div>\n\n            <label>\n              Category\n            </label>\n\n            <select name=\"category\">\n\n              <option>\n                Social / Befriending\n              </option>\n\n              <option>\n                Sports / Wellbeing\n              </option>\n\n              <option>\n                Arts / Culture\n              </option>\n\n              <option>\n                Skills / Volunteering\n              </option>\n\n              <option>\n                Other\n              </option>\n\n            </select>\n\n          </div>\n\n\n          <div>\n\n            <label>\n              Who is it for?\n            </label>\n\n            <input name=\"audience\">\n\n          </div>\n\n\n          <div>\n\n            <label>\n              When does it happen?\n            </label>\n\n            <input\n              name=\"schedule\"\n              placeholder=\"e.g. Every Friday, 10am–12pm\"\n            >\n\n          </div>\n\n\n          <div>\n\n            <label>\n              Type of activity\n            </label>\n\n            <select name=\"eventType\">\n\n              <option>\n                Regular / ongoing\n              </option>\n\n              <option>\n                One-off event\n              </option>\n\n            </select>\n\n          </div>\n\n\n          <div>\n\n            <label>\n              Date of one-off event\n            </label>\n\n            <input\n              type=\"date\"\n              name=\"endDate\"\n            >\n\n          </div>\n\n\n          <div>\n\n            <label>\n              Location\n            </label>\n\n            <input name=\"location\">\n\n          </div>\n\n\n          <div>\n\n            <label>\n              Cost\n            </label>\n\n            <input name=\"cost\">\n\n          </div>\n\n\n          <div>\n\n            <label>\n              Accessibility information\n            </label>\n\n            <input name=\"accessibility\">\n\n          </div>\n\n\n          <div>\n\n            <label>\n              Telephone\n            </label>\n\n            <input name=\"phone\">\n\n          </div>\n\n\n          <div>\n\n            <label>\n              Contact email *\n            </label>\n\n            <input\n              type=\"email\"\n              name=\"email\"\n              required\n            >\n\n          </div>\n\n\n          <div>\n\n            <label>\n              Website\n            </label>\n\n            <input name=\"website\">\n\n          </div>\n\n\n        </div>\n\n\n        <p class=\"note\">\n          Submitted activities may be reviewed before appearing publicly.\n        </p>\n\n\n        <div class=\"form-actions\">\n\n          <button\n            type=\"button\"\n            class=\"secondary\"\n            data-close=\"submitModal\"\n          >\n            Cancel\n          </button>\n\n          <button\n            type=\"submit\"\n            class=\"primary\"\n          >\n            Submit activity\n          </button>\n\n        </div>\n\n\n        <div\n          class=\"note\"\n          id=\"formMsg\"\n        ></div>\n\n\n      </form>\n\n    </div>\n\n  </div>\n\n</div>\n\n\n<script src=\"https://unpkg.com/leaflet@1.9.4/dist/leaflet.js\"></script>\n<script src=\"https://unpkg.com/leaflet.markercluster@1.5.3/dist/leaflet.markercluster.js\"></script>\n\n\n<script>\n\n/* =========================================================\n   DATA CONNECTION\n   ========================================================= */\n\nconst APPS_SCRIPT_URL =\n\"https://script.google.com/macros/s/AKfycby4h3hzjz5qHldxs_9ZoheO8GF9wzsE0C81YBEpVUPipuhUurLkoWTy7RKNWdfbDoUxPg/exec\";\n\n\nconst COL={\n\n  title:\"Title\",\n  organisation:\"Organisation\",\n  description:\"Description\",\n  category:\"Category\",\n  audience:\"Audience\",\n  location:\"Location\",\n  schedule:\"Schedule\",\n  contact:\"ContactEmail\",\n  website:\"Website\",\n  lat:\"Latitude\",\n  lng:\"Longitude\",\n  status:\"Status\",\n  eventType:\"EventType\",\n  endDate:\"EndDate\",\n  phone:\"Phone\",\n  timestamp:\"Timestamp\"\n\n};\n\n\nconst SWALE_BOUNDS=L.latLngBounds(\n  [51.27,0.57],\n  [51.46,0.93]\n);\n\n\nconst SWALE_CENTRE=[\n  51.34,\n  0.77\n];\n\n\nconst PAGE_SIZE=9;\n\n\nconst $=id=>\n  document.getElementById(id);\n\n\nlet rows=[];\nlet filtered=[];\nlet page=1;\nlet selectedCat=\"\";\nlet view=\"list\";\nlet map=null;\nlet markers=null;\n\n\n/* =========================================================\n   HELPERS\n   ========================================================= */\n\nfunction norm(v){\n\n  return String(v||\"\")\n    .toLowerCase()\n    .trim();\n\n}\n\n\nfunction esc(v){\n\n  return String(v??\"\")\n\n    .replaceAll(\"&\",\"&amp;\")\n    .replaceAll(\"<\",\"&lt;\")\n    .replaceAll(\">\",\"&gt;\")\n    .replaceAll('\"',\"&quot;\");\n\n}\n\n\nfunction attr(v){\n\n  return esc(v)\n    .replaceAll(\"'\",\"&#39;\");\n\n}\n\n\nfunction url(v){\n\n  try{\n\n    const u=\n      new URL(String(v||\"\"));\n\n    return /^https?:$/.test(\n      u.protocol\n    );\n\n  }catch{\n\n    return false;\n\n  }\n\n}\n\n\n/* =========================================================\n   CATEGORIES\n   ========================================================= */\n\nfunction publicCat(raw){\n\n  const c=norm(raw);\n\n\n  if(\n    c===\"social / befriending\" ||\n    c===\"social/befriending\"\n  ){\n\n    return \"Social / Befriending\";\n\n  }\n\n\n  if(\n    c===\"sports / wellbeing\" ||\n    c===\"sports/wellbeing\"\n  ){\n\n    return \"Sports / Wellbeing\";\n\n  }\n\n\n  if(\n    c===\"arts / culture\" ||\n    c===\"arts/culture\"\n  ){\n\n    return \"Arts / Culture\";\n\n  }\n\n\n  if(\n    c===\"skills / volunteering\" ||\n    c===\"skills/volunteering\"\n  ){\n\n    return \"Skills / Volunteering\";\n\n  }\n\n\n  return \"Other\";\n\n}\n\n\nfunction catLabel(c){\n\n  return c || \"Other\";\n\n}\n\n\n/* =========================================================\n   AREA\n   ========================================================= */\n\nfunction areaOf(r){\n\n  const s=\n    norm(r[COL.location]);\n\n\n  if(\n    /sheerness|queenborough|minster|leysdown|eastchurch|warden|sheppey/.test(s)\n  ){\n\n    return \"Sheppey\";\n\n  }\n\n\n  if(\n    /faversham|ospringe|selling|newnham|davington|preston/.test(s)\n  ){\n\n    return \"Faversham\";\n\n  }\n\n\n  if(\n    /sittingbourne|kemsley|milton regis|murston|bapchild|teynham|newington|hartlip|upchurch|iwade/.test(s)\n  ){\n\n    return \"Sittingbourne\";\n\n  }\n\n\n  return \"Wider Swale\";\n\n}\n\n\n/* =========================================================\n   EXPIRED ONE-OFF EVENTS\n   ========================================================= */\n\nfunction expired(r){\n\n  const type=\n    norm(r[COL.eventType]);\n\n\n  if(\n    !type.includes(\"one\")\n  ){\n\n    return false;\n\n  }\n\n\n  const d=\n    new Date(r[COL.endDate]);\n\n\n  if(\n    isNaN(d)\n  ){\n\n    return false;\n\n  }\n\n\n  d.setHours(\n    23,\n    59,\n    59,\n    999\n  );\n\n\n  return d < new Date();\n\n}\n\n\n/* =========================================================\n   AUDIENCE FILTER\n   ========================================================= */\n\nfunction ageMatch(\n  r,\n  choice\n){\n\n  if(!choice){\n\n    return true;\n\n  }\n\n\n  const s=\n    norm(r[COL.audience]);\n\n\n  if(\n    choice===\"Children\"\n  ){\n\n    return /child|children|family|families|under 12|0-/.test(s);\n\n  }\n\n\n  if(\n    choice===\"Young people\"\n  ){\n\n    return /young|youth|teen|12-17|16-25|under 25/.test(s);\n\n  }\n\n\n  if(\n    choice===\"Adults\"\n  ){\n\n    return /adult|18\\+|all ages|everyone/.test(s);\n\n  }\n\n\n  if(\n    choice===\"Older people\"\n  ){\n\n    return /older|55\\+|60\\+|65\\+|senior/.test(s);\n\n  }\n\n\n  return true;\n\n}\n\n\n/* =========================================================\n   DATE FILTERING\n   ========================================================= */\n\nfunction dateOnly(value){\n\n  if(!value){\n\n    return null;\n\n  }\n\n\n  const d=\n    new Date(value);\n\n\n  if(\n    isNaN(d)\n  ){\n\n    return null;\n\n  }\n\n\n  return new Date(\n    d.getFullYear(),\n    d.getMonth(),\n    d.getDate()\n  );\n\n}\n\n\nfunction startOfToday(){\n\n  const d=\n    new Date();\n\n\n  return new Date(\n    d.getFullYear(),\n    d.getMonth(),\n    d.getDate()\n  );\n\n}\n\n\nfunction endOfThisWeek(){\n\n  const d=\n    startOfToday();\n\n\n  const daysToSunday=\n    (7-d.getDay())%7;\n\n\n  d.setDate(\n    d.getDate()+\n    daysToSunday\n  );\n\n\n  d.setHours(\n    23,\n    59,\n    59,\n    999\n  );\n\n\n  return d;\n\n}\n\n\nfunction recurringOccursBetween(\n  schedule,\n  start,\n  end\n){\n\n  const s=\n    norm(schedule);\n\n\n  const days=[\n    \"sunday\",\n    \"monday\",\n    \"tuesday\",\n    \"wednesday\",\n    \"thursday\",\n    \"friday\",\n    \"saturday\"\n  ];\n\n\n  for(\n    let i=0;\n    i<days.length;\n    i++\n  ){\n\n    if(\n      s.includes(days[i])\n    ){\n\n      const d=\n        new Date(start);\n\n\n      const delta=\n        (i-d.getDay()+7)%7;\n\n\n      d.setDate(\n        d.getDate()+\n        delta\n      );\n\n\n      if(\n        d<=end\n      ){\n\n        return true;\n\n      }\n\n    }\n\n  }\n\n\n  return false;\n\n}\n\n\nfunction whenMatch(\n  r,\n  choice\n){\n\n  if(!choice){\n\n    return true;\n\n  }\n\n\n  const type=\n    norm(r[COL.eventType]);\n\n\n  const isOneOff=\n    type.includes(\"one\");\n\n\n  const eventDate=\n    dateOnly(\n      r[COL.endDate]\n    );\n\n\n  const today=\n    startOfToday();\n\n\n  if(\n    choice===\"oneoff\"\n  ){\n\n    return isOneOff;\n\n  }\n\n\n  if(\n    choice===\"ongoing\"\n  ){\n\n    return !isOneOff;\n\n  }\n\n\n  if(\n    choice===\"today\"\n  ){\n\n    if(isOneOff){\n\n      return (\n        !!eventDate &&\n        eventDate.getTime()===\n        today.getTime()\n      );\n\n    }\n\n\n    return recurringOccursBetween(\n      r[COL.schedule],\n      today,\n      today\n    );\n\n  }\n\n\n  if(\n    choice===\"week\"\n  ){\n\n    const end=\n      endOfThisWeek();\n\n\n    if(isOneOff){\n\n      return (\n        !!eventDate &&\n        eventDate>=today &&\n        eventDate<=end\n      );\n\n    }\n\n\n    return recurringOccursBetween(\n      r[COL.schedule],\n      today,\n      end\n    );\n\n  }\n\n\n  return true;\n\n}\n\n\n/* =========================================================\n   FILTER ACTIVITIES\n   ========================================================= */\n\nfunction apply(){\n\n  const q=\n    norm(\n      $(\"q\").value\n    );\n\n\n  const area=\n    $(\"area\").value;\n\n\n  const age=\n    $(\"age\").value;\n\n\n  const when=\n    $(\"when\").value;\n\n\n  filtered=\n    rows.filter(r=>{\n\n\n      if(\n        selectedCat &&\n        publicCat(\n          r[COL.category]\n        )!==selectedCat\n      ){\n\n        return false;\n\n      }\n\n\n      if(\n        area &&\n        areaOf(r)!==area\n      ){\n\n        return false;\n\n      }\n\n\n      if(\n        age &&\n        !ageMatch(\n          r,\n          age\n        )\n      ){\n\n        return false;\n\n      }\n\n\n      if(\n        when &&\n        !whenMatch(\n          r,\n          when\n        )\n      ){\n\n        return false;\n\n      }\n\n\n      if(q){\n\n        const hay=[\n\n          r[COL.title],\n          r[COL.organisation],\n          r[COL.description],\n          r[COL.location],\n          r[COL.schedule],\n          r[COL.category],\n          r[COL.audience]\n\n        ]\n\n        .map(norm)\n\n        .join(\" \");\n\n\n        if(\n          !hay.includes(q)\n        ){\n\n          return false;\n\n        }\n\n      }\n\n\n      return true;\n\n    });\n\n\n  page=1;\n\n\n  render();\n\n}\n\n\n/* =========================================================\n   RENDER\n   ========================================================= */\n\nfunction render(){\n\n  $(\"count\").textContent=\n    `${filtered.length} ${\n      filtered.length===1\n        ? \"activity\"\n        : \"activities\"\n    } found`;\n\n\n  $(\"heroCount\").textContent=\n    `${rows.length} ${\n      rows.length===1\n        ? \"activity\"\n        : \"activities\"\n    } currently listed across Swale.`;\n\n\n  renderList();\n\n\n  if(map){\n\n    renderMap();\n\n  }\n\n}\n\n\n/* =========================================================\n   ACTIVITY CARDS\n   ========================================================= */\n\nfunction renderList(){\n\n  const box=\n    $(\"listView\");\n\n\n  const pager=\n    $(\"pagination\");\n\n\n  box.innerHTML=\"\";\n  pager.innerHTML=\"\";\n\n\n  const pages=\n    Math.max(\n      1,\n      Math.ceil(\n        filtered.length /\n        PAGE_SIZE\n      )\n    );\n\n\n  page=\n    Math.min(\n      page,\n      pages\n    );\n\n\n  const items=\n    filtered.slice(\n\n      (page-1)*PAGE_SIZE,\n\n      page*PAGE_SIZE\n\n    );\n\n\n  if(\n    !items.length\n  ){\n\n    box.innerHTML=`\n\n      <div class=\"empty\">\n\n        <strong>\n          No activities match those filters.\n        </strong>\n\n        <br>\n\n        Try widening your search\n        or clearing the filters.\n\n      </div>\n\n    `;\n\n\n    return;\n\n  }\n\n\n  items.forEach(r=>{\n\n\n    const c=\n      publicCat(\n        r[COL.category]\n      );\n\n\n    const el=\n      document.createElement(\n        \"article\"\n      );\n\n\n    const catClass={\n\n      \"Social / Befriending\":\n        \"cat-social\",\n\n      \"Sports / Wellbeing\":\n        \"cat-sports\",\n\n      \"Arts / Culture\":\n        \"cat-arts\",\n\n      \"Skills / Volunteering\":\n        \"cat-skills\",\n\n      \"Other\":\n        \"cat-other\"\n\n    }[c] || \"cat-other\";\n\n\n    el.className=\n      `card ${catClass}`;\n\n\n    const loc=\n      url(\n        r[COL.location]\n      )\n        ? \"\"\n        : r[COL.location] || \"\";\n\n\n    el.innerHTML=`\n\n      <span class=\"pill\">\n\n        ${esc(\n          catLabel(c)\n        )}\n\n      </span>\n\n\n      <h3>\n\n        ${esc(\n          r[COL.title] ||\n          \"Untitled activity\"\n        )}\n\n      </h3>\n\n\n      ${\n        r[COL.organisation]\n        ? `\n          <div class=\"org\">\n            ${esc(\n              r[COL.organisation]\n            )}\n          </div>\n        `\n        : \"\"\n      }\n\n\n      ${\n        r[COL.schedule]\n        ? `\n          <div class=\"meta\">\n            📅 ${esc(\n              r[COL.schedule]\n            )}\n          </div>\n        `\n        : \"\"\n      }\n\n\n      ${\n        loc\n        ? `\n          <div class=\"meta\">\n            📍 ${esc(loc)}\n          </div>\n        `\n        : \"\"\n      }\n\n\n      ${\n        r[COL.audience]\n        ? `\n          <div class=\"meta\">\n            👥 ${esc(\n              r[COL.audience]\n            )}\n          </div>\n        `\n        : \"\"\n      }\n\n\n      ${\n        r[COL.description]\n        ? `\n          <div class=\"desc\">\n            ${esc(\n              r[COL.description]\n            )}\n          </div>\n        `\n        : \"\"\n      }\n\n\n      <div class=\"card-actions\">\n\n        <button\n          class=\"primary detail-open\"\n        >\n          View activity\n        </button>\n\n\n        ${\n          directionsLink(r)\n          ? `\n            <a\n              class=\"secondary\"\n              target=\"_blank\"\n              rel=\"noopener\"\n              href=\"${directionsLink(r)}\"\n            >\n              Get directions\n            </a>\n          `\n          : \"\"\n        }\n\n      </div>\n\n    `;\n\n\n    el\n      .querySelector(\n        \".detail-open\"\n      )\n      .onclick=\n        ()=>openDetail(r);\n\n\n    box.appendChild(el);\n\n  });\n\n\n  if(\n    pages>1\n  ){\n\n    const prev=\n      document.createElement(\n        \"button\"\n      );\n\n\n    const lab=\n      document.createElement(\n        \"span\"\n      );\n\n\n    const next=\n      document.createElement(\n        \"button\"\n      );\n\n\n    prev.textContent=\n      \"Previous\";\n\n\n    next.textContent=\n      \"Next\";\n\n\n    lab.textContent=\n      `Page ${page} of ${pages}`;\n\n\n    prev.disabled=\n      page===1;\n\n\n    next.disabled=\n      page===pages;\n\n\n    prev.onclick=()=>{\n\n      page--;\n\n      renderList();\n\n      scrollToResults();\n\n    };\n\n\n    next.onclick=()=>{\n\n      page++;\n\n      renderList();\n\n      scrollToResults();\n\n    };\n\n\n    pager.append(\n      prev,\n      lab,\n      next\n    );\n\n  }\n\n}\n\n\n/* =========================================================\n   GOOGLE MAPS DIRECTIONS\n   ========================================================= */\n\nfunction directionsLink(r){\n\n  let lat=\n    parseFloat(\n      r[COL.lat]\n    );\n\n\n  let lng=\n    parseFloat(\n      r[COL.lng]\n    );\n\n\n  if(\n    Number.isFinite(lat) &&\n    Number.isFinite(lng)\n  ){\n\n    return (\n      \"https://www.google.com/maps/dir/?api=1&destination=\" +\n      lat +\n      \",\" +\n      lng\n    );\n\n  }\n\n\n  const loc=\n    String(\n      r[COL.location] ||\n      \"\"\n    ).trim();\n\n\n  return (\n    loc &&\n    !url(loc)\n  )\n    ? (\n        \"https://www.google.com/maps/dir/?api=1&destination=\" +\n        encodeURIComponent(\n          loc +\n          \", Swale, Kent\"\n        )\n      )\n    : \"\";\n\n}\n\n\n/* =========================================================\n   ACTIVITY DETAIL\n   ========================================================= */\n\nfunction openDetail(r){\n\n  const loc=\n    url(\n      r[COL.location]\n    )\n      ? \"\"\n      : r[COL.location] || \"\";\n\n\n  const web=\n    r[COL.website] || \"\";\n\n\n  const mail=\n    r[COL.contact] || \"\";\n\n\n  const phone=\n    r[COL.phone] || \"\";\n\n\n  $(\"detailBody\").innerHTML=`\n\n    <span class=\"pill\">\n\n      ${esc(\n        catLabel(\n          publicCat(\n            r[COL.category]\n          )\n        )\n      )}\n\n    </span>\n\n\n    <h3 class=\"detail-title\">\n\n      ${esc(\n        r[COL.title] ||\n        \"Activity\"\n      )}\n\n    </h3>\n\n\n    ${\n      r[COL.organisation]\n      ? `\n        <div class=\"org\">\n          ${esc(\n            r[COL.organisation]\n          )}\n        </div>\n      `\n      : \"\"\n    }\n\n\n    ${\n      r[COL.schedule]\n      ? `\n        <div>\n          📅\n          <strong>\n            ${esc(\n              r[COL.schedule]\n            )}\n          </strong>\n        </div>\n      `\n      : \"\"\n    }\n\n\n    ${\n      loc\n      ? `\n        <div>\n          📍 ${esc(loc)}\n        </div>\n      `\n      : \"\"\n    }\n\n\n    ${\n      r[COL.audience]\n      ? `\n        <div>\n          👥 ${esc(\n            r[COL.audience]\n          )}\n        </div>\n      `\n      : \"\"\n    }\n\n\n    ${\n      r[COL.description]\n      ? `\n        <div class=\"detail-desc\">\n          ${esc(\n            r[COL.description]\n          )}\n        </div>\n      `\n      : \"\"\n    }\n\n\n    <div class=\"detail-actions\">\n\n\n      ${\n        directionsLink(r)\n        ? `\n          <a\n            class=\"primary\"\n            target=\"_blank\"\n            rel=\"noopener\"\n            href=\"${directionsLink(r)}\"\n          >\n            Get directions\n          </a>\n        `\n        : \"\"\n      }\n\n\n      ${\n        mail\n        ? `\n          <a\n            class=\"secondary\"\n            href=\"mailto:${attr(mail)}\"\n          >\n            Email organiser\n          </a>\n        `\n        : \"\"\n      }\n\n\n      ${\n        phone\n        ? `\n          <a\n            class=\"secondary\"\n            href=\"tel:${attr(phone)}\"\n          >\n            Call organiser\n          </a>\n        `\n        : \"\"\n      }\n\n\n      ${\n        web &&\n        url(web)\n        ? `\n          <a\n            class=\"secondary\"\n            target=\"_blank\"\n            rel=\"noopener\"\n            href=\"${attr(web)}\"\n          >\n            Visit website\n          </a>\n        `\n        : \"\"\n      }\n\n\n    </div>\n\n  `;\n\n\n  openModal(\n    \"detailModal\"\n  );\n\n}\n\n\n/* =========================================================\n   MAP\n   ========================================================= */\n\nfunction ensureMap(){\n\n  if(map){\n\n    return;\n\n  }\n\n\n  map=\n    L.map(\n      \"map\",\n      {\n        scrollWheelZoom:false,\n        maxBounds:\n          SWALE_BOUNDS.pad(.15)\n      }\n    )\n    .setView(\n      SWALE_CENTRE,\n      11\n    );\n\n\n  L.tileLayer(\n    \"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png\",\n    {\n      attribution:\n        \"© OpenStreetMap contributors\"\n    }\n  )\n  .addTo(map);\n\n\n  markers=\n    typeof L.markerClusterGroup===\n    \"function\"\n\n      ? L.markerClusterGroup({\n\n          showCoverageOnHover:false,\n\n          iconCreateFunction:c=>\n\n            L.divIcon({\n\n              className:\"\",\n\n              html:\n                `<div class=\"cluster\">\n                  ${c.getChildCount()}\n                </div>`,\n\n              iconSize:[\n                42,\n                42\n              ]\n\n            })\n\n        })\n        .addTo(map)\n\n      : L.layerGroup()\n        .addTo(map);\n\n}\n\n\nfunction renderMap(){\n\n  ensureMap();\n\n\n  markers.clearLayers();\n\n\n  const b=\n    L.latLngBounds([]);\n\n\n  let n=0;\n\n\n  filtered.forEach(r=>{\n\n\n    let lat=\n      parseFloat(\n        r[COL.lat]\n      );\n\n\n    let lng=\n      parseFloat(\n        r[COL.lng]\n      );\n\n\n    if(\n      lng>51 &&\n      lat>.4 &&\n      lat<1.1\n    ){\n\n      [lat,lng]=[\n        lng,\n        lat\n      ];\n\n    }\n\n\n    if(\n      Number.isFinite(lat) &&\n      Number.isFinite(lng)\n    ){\n\n      n++;\n\n\n      const icon=\n        L.divIcon({\n\n          className:\"\",\n\n          html:\n            '<div class=\"marker\"></div>',\n\n          iconSize:[\n            32,\n            32\n          ],\n\n          iconAnchor:[\n            16,\n            30\n          ]\n\n        });\n\n\n      const marker=\n        L.marker(\n          [lat,lng],\n          {icon}\n        );\n\n\n      const popup=\n        document.createElement(\n          \"div\"\n        );\n\n\n      popup.style.minWidth=\n        \"220px\";\n\n\n      const desc=\n        String(\n          r[COL.description] ||\n          \"\"\n        ).trim();\n\n\n      popup.innerHTML=`\n\n        <div\n          style=\"\n            font-weight:800;\n            font-size:15px;\n            margin-bottom:3px;\n            color:#07366d;\n          \"\n        >\n          ${esc(\n            r[COL.title] ||\n            \"Activity\"\n          )}\n        </div>\n\n\n        ${\n          r[COL.organisation]\n          ? `\n            <div\n              style=\"\n                margin-bottom:7px;\n                color:#52606d;\n              \"\n            >\n              ${esc(\n                r[COL.organisation]\n              )}\n            </div>\n          `\n          : \"\"\n        }\n\n\n        ${\n          r[COL.schedule]\n          ? `\n            <div style=\"margin:4px 0\">\n              📅 ${esc(\n                r[COL.schedule]\n              )}\n            </div>\n          `\n          : \"\"\n        }\n\n\n        ${\n          r[COL.location]\n          ? `\n            <div style=\"margin:4px 0\">\n              📍 ${esc(\n                r[COL.location]\n              )}\n            </div>\n          `\n          : \"\"\n        }\n\n\n        ${\n          r[COL.audience]\n          ? `\n            <div style=\"margin:4px 0\">\n              👥 ${esc(\n                r[COL.audience]\n              )}\n            </div>\n          `\n          : \"\"\n        }\n\n\n        ${\n          desc\n          ? `\n            <div style=\"margin:8px 0\">\n              ${esc(\n                desc.length>140\n                  ? desc.slice(\n                      0,\n                      137\n                    )+\"...\"\n                  : desc\n              )}\n            </div>\n          `\n          : \"\"\n        }\n\n      `;\n\n\n      const actions=\n        document.createElement(\n          \"div\"\n        );\n\n\n      actions.style.cssText=\n        \"display:flex;gap:7px;flex-wrap:wrap;margin-top:9px\";\n\n\n      const details=\n        document.createElement(\n          \"button\"\n        );\n\n\n      details.type=\n        \"button\";\n\n\n      details.textContent=\n        \"View activity\";\n\n\n      details.className=\n        \"primary\";\n\n\n      details.style.cssText=\n        \"padding:8px 10px;font-size:12px\";\n\n\n      details.onclick=()=>{\n\n        map.closePopup();\n\n        openDetail(r);\n\n      };\n\n\n      actions.appendChild(\n        details\n      );\n\n\n      const dir=\n        directionsLink(r);\n\n\n      if(dir){\n\n        const a=\n          document.createElement(\n            \"a\"\n          );\n\n\n        a.href=\n          dir;\n\n\n        a.target=\n          \"_blank\";\n\n\n        a.rel=\n          \"noopener\";\n\n\n        a.textContent=\n          \"Get directions\";\n\n\n        a.className=\n          \"secondary\";\n\n\n        a.style.cssText=\n          \"padding:8px 10px;font-size:12px\";\n\n\n        actions.appendChild(\n          a\n        );\n\n      }\n\n\n      popup.appendChild(\n        actions\n      );\n\n\n      marker\n        .bindPopup(\n          popup,\n          {\n            maxWidth:320\n          }\n        )\n        .addTo(\n          markers\n        );\n\n\n      b.extend([\n        lat,\n        lng\n      ]);\n\n    }\n\n  });\n\n\n  if(\n    n>1\n  ){\n\n    map.fitBounds(\n      b.pad(.12)\n    );\n\n  }else{\n\n    map.setView(\n      SWALE_CENTRE,\n      11\n    );\n\n  }\n\n\n  setTimeout(\n    ()=>map.invalidateSize(),\n    50\n  );\n\n}\n\n\n/* =========================================================\n   LIST / MAP VIEW\n   ========================================================= */\n\nfunction setView(v){\n\n  view=v;\n\n\n  $(\"listBtn\")\n    .classList\n    .toggle(\n      \"active\",\n      v===\"list\"\n    );\n\n\n  $(\"mapBtn\")\n    .classList\n    .toggle(\n      \"active\",\n      v===\"map\"\n    );\n\n\n  $(\"listView\")\n    .classList\n    .toggle(\n      \"hidden\",\n      v!==\"list\"\n    );\n\n\n  $(\"pagination\")\n    .classList\n    .toggle(\n      \"hidden\",\n      v!==\"list\"\n    );\n\n\n  $(\"mapView\")\n    .classList\n    .toggle(\n      \"hidden\",\n      v!==\"map\"\n    );\n\n\n  if(\n    v===\"map\"\n  ){\n\n    renderMap();\n\n  }\n\n}\n\n\n/* =========================================================\n   CLEAR FILTERS\n   ========================================================= */\n\nfunction clearFilters(){\n\n  $(\"q\").value=\"\";\n  $(\"area\").value=\"\";\n  $(\"age\").value=\"\";\n  $(\"when\").value=\"\";\n\n\n  selectedCat=\"\";\n\n\n  document\n    .querySelectorAll(\".cat\")\n    .forEach(\n      x=>\n        x.classList.remove(\n          \"active\"\n        )\n    );\n\n\n  apply();\n\n}\n\n\n/* =========================================================\n   SCROLLING\n   ========================================================= */\n\nfunction scrollToResults(){\n\n  document\n    .querySelector(\n      \".results\"\n    )\n    .scrollIntoView({\n\n      behavior:\"smooth\",\n      block:\"start\"\n\n    });\n\n}\n\n\n/* =========================================================\n   MODALS\n   ========================================================= */\n\nfunction openModal(id){\n\n  $(id)\n    .classList\n    .add(\"open\");\n\n\n  $(id)\n    .setAttribute(\n      \"aria-hidden\",\n      \"false\"\n    );\n\n}\n\n\nfunction closeModal(id){\n\n  $(id)\n    .classList\n    .remove(\"open\");\n\n\n  $(id)\n    .setAttribute(\n      \"aria-hidden\",\n      \"true\"\n    );\n\n}\n\n\ndocument\n  .querySelectorAll(\n    \"[data-close]\"\n  )\n  .forEach(\n\n    b=>\n      b.onclick=\n        ()=>closeModal(\n          b.dataset.close\n        )\n\n  );\n\n\ndocument\n  .querySelectorAll(\n    \".modal-bg\"\n  )\n  .forEach(\n\n    m=>\n      m.onclick=e=>{\n\n        if(\n          e.target===m\n        ){\n\n          closeModal(\n            m.id\n          );\n\n        }\n\n      }\n\n  );\n\n\ndocument.addEventListener(\n  \"keydown\",\n  e=>{\n\n    if(\n      e.key===\"Escape\"\n    ){\n\n      document\n        .querySelectorAll(\n          \".modal-bg.open\"\n        )\n        .forEach(\n          m=>\n            closeModal(\n              m.id\n            )\n        );\n\n    }\n\n  }\n);\n\n\n/* =========================================================\n   CONTROLS\n   ========================================================= */\n\n$(\"openSubmit\").onclick=\n  ()=>openModal(\n    \"submitModal\"\n  );\n\n\n$(\"browseBtn\").onclick=()=>{\n\n  setView(\"list\");\n\n  scrollToResults();\n\n};\n\n\n$(\"heroMapBtn\").onclick=()=>{\n\n  setView(\"map\");\n\n  scrollToResults();\n\n};\n\n\n$(\"searchBtn\").onclick=()=>{\n\n  apply();\n\n  scrollToResults();\n\n};\n\n\n$(\"q\").onkeydown=e=>{\n\n  if(\n    e.key===\"Enter\"\n  ){\n\n    $(\"searchBtn\").click();\n\n  }\n\n};\n\n\n[\"area\",\"age\",\"when\"]\n  .forEach(\n\n    id=>\n      $(id).onchange=\n        apply\n\n  );\n\n\n$(\"q\").oninput=\n  apply;\n\n\n$(\"clearBtn\").onclick=\n  clearFilters;\n\n\n$(\"listBtn\").onclick=\n  ()=>setView(\"list\");\n\n\n$(\"mapBtn\").onclick=\n  ()=>setView(\"map\");\n\n\ndocument\n  .querySelectorAll(\n    \".cat\"\n  )\n  .forEach(\n\n    b=>\n      b.onclick=()=>{\n\n\n        selectedCat=\n\n          selectedCat===\n          b.dataset.cat\n\n            ? \"\"\n\n            : b.dataset.cat;\n\n\n        document\n          .querySelectorAll(\n            \".cat\"\n          )\n          .forEach(\n\n            x=>\n              x.classList.toggle(\n\n                \"active\",\n\n                x.dataset.cat===\n                selectedCat\n\n              )\n\n          );\n\n\n        apply();\n\n        scrollToResults();\n\n      }\n\n  );\n\n\n/* =========================================================\n   DATA CACHE\n   ========================================================= */\n\nconst CACHE_KEY=\n  \"scvsActivitiesCacheV1\";\n\n\nconst CACHE_MAX_AGE=\n  30*60*1000;\n\n\nfunction useActivityData(data){\n\n  rows=\n    (\n      Array.isArray(data)\n        ? data\n        : []\n    )\n\n    .filter(\n      r=>!expired(r)\n    )\n\n    .sort(\n      (a,b)=>\n\n        new Date(\n          b[COL.timestamp] ||\n          0\n        )\n\n        -\n\n        new Date(\n          a[COL.timestamp] ||\n          0\n        )\n    );\n\n\n  filtered=[\n    ...rows\n  ];\n\n\n  $(\"loading\")\n    .classList\n    .add(\n      \"hidden\"\n    );\n\n\n  $(\"listView\")\n    .classList\n    .remove(\n      \"hidden\"\n    );\n\n\n  render();\n\n}\n\n\nlet showedCache=\n  false;\n\n\ntry{\n\n\n  const cached=\n    JSON.parse(\n\n      localStorage.getItem(\n        CACHE_KEY\n      )\n\n      ||\n\n      \"null\"\n\n    );\n\n\n  if(\n\n    cached &&\n\n    Array.isArray(\n      cached.data\n    ) &&\n\n    (\n      Date.now()-\n      cached.saved\n    )\n\n    <\n\n    CACHE_MAX_AGE\n\n  ){\n\n    useActivityData(\n      cached.data\n    );\n\n\n    showedCache=\n      true;\n\n  }\n\n\n}catch(e){}\n\n\n/* =========================================================\n   FETCH LATEST DATA\n   ========================================================= */\n\nfetch(\n  APPS_SCRIPT_URL,\n  {\n    cache:\"no-store\"\n  }\n)\n\n.then(\n  r=>\n\n    r.ok\n\n      ? r.json()\n\n      : Promise.reject(\n          r.status\n        )\n)\n\n.then(data=>{\n\n\n  try{\n\n\n    localStorage.setItem(\n\n      CACHE_KEY,\n\n      JSON.stringify({\n\n        saved:\n          Date.now(),\n\n        data:\n          data\n\n      })\n\n    );\n\n\n  }catch(e){}\n\n\n  useActivityData(\n    data\n  );\n\n})\n\n.catch(err=>{\n\n\n  if(\n    !showedCache\n  ){\n\n    $(\"loading\").innerHTML=\n      \"Sorry, the activities could not be loaded. Please try again shortly.\";\n\n  }\n\n\n  console.error(\n    err\n  );\n\n});\n\n\n/* =========================================================\n   SUBMIT ACTIVITY\n   ========================================================= */\n\nconst form=\n  $(\"activityForm\");\n\n\nconst msg=\n  $(\"formMsg\");\n\n\nform.onsubmit=\n  async e=>{\n\n\n    e.preventDefault();\n\n\n    msg.textContent=\n      \"Sending...\";\n\n\n    const data=\n      Object.fromEntries(\n\n        new FormData(\n          form\n        ).entries()\n\n      );\n\n\n    if(\n\n      norm(\n        data.eventType\n      ).startsWith(\"one\")\n\n      &&\n\n      !data.endDate\n\n    ){\n\n      msg.textContent=\n        \"Please add the date for a one-off event.\";\n\n\n      return;\n\n    }\n\n\n    try{\n\n\n      await fetch(\n\n        APPS_SCRIPT_URL,\n\n        {\n\n          method:\"POST\",\n\n          mode:\"no-cors\",\n\n          headers:{\n\n            \"Content-Type\":\n              \"application/json\"\n\n          },\n\n          body:\n            JSON.stringify(\n              data\n            )\n\n        }\n\n      );\n\n\n      form.reset();\n\n\n      $(\"success\")\n        .style\n        .display=\n          \"block\";\n\n\n      msg.textContent=\n        \"\";\n\n\n      setTimeout(\n\n        ()=>closeModal(\n          \"submitModal\"\n        ),\n\n        1800\n\n      );\n\n\n    }catch(err){\n\n\n      msg.textContent=\n        \"Sorry, something went wrong. Please try again.\";\n\n    }\n\n  };\n\n</script>\n\n</body>\n</html>","embed_html_app1headerHtml":""},"metaData":{"position":{"left":-561.9921875,"top":160},"size":{"width":1136,"height":2404}}}]}],"offset":{"left":230.99609375,"top":63.984375}}],"connections":{"targetConnections":{},"sourceConnections":{}},"customStatesProperties":{},"pageId":"id1790341329143","version":17.004,"id":"id1790341563628","relativePoint":{"left":230.99609375,"top":63.984375}}