diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b512c09
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+node_modules
\ No newline at end of file
diff --git a/assets/faq/faq-icon.png b/assets/faq/faq-icon.png
new file mode 100644
index 0000000..3734c5e
Binary files /dev/null and b/assets/faq/faq-icon.png differ
diff --git a/assets/hero/hero-bg.png b/assets/hero/hero-bg.png
new file mode 100644
index 0000000..5c2fef8
Binary files /dev/null and b/assets/hero/hero-bg.png differ
diff --git a/assets/hero/hero-image-left.png b/assets/hero/hero-image-left.png
new file mode 100644
index 0000000..ab2dfe7
Binary files /dev/null and b/assets/hero/hero-image-left.png differ
diff --git a/assets/hero/hero-image-right.png b/assets/hero/hero-image-right.png
new file mode 100644
index 0000000..8c1c09f
Binary files /dev/null and b/assets/hero/hero-image-right.png differ
diff --git a/assets/hero/hero-logo.png b/assets/hero/hero-logo.png
new file mode 100644
index 0000000..abd49a0
Binary files /dev/null and b/assets/hero/hero-logo.png differ
diff --git a/assets/highlights/highlights-icon.png b/assets/highlights/highlights-icon.png
new file mode 100644
index 0000000..6155df8
Binary files /dev/null and b/assets/highlights/highlights-icon.png differ
diff --git a/assets/location/location-icon.png b/assets/location/location-icon.png
new file mode 100644
index 0000000..1a1cbb0
Binary files /dev/null and b/assets/location/location-icon.png differ
diff --git a/assets/logo.png b/assets/logo.png
new file mode 100644
index 0000000..2ca1da7
Binary files /dev/null and b/assets/logo.png differ
diff --git a/assets/meet-your-host/host-icon.png b/assets/meet-your-host/host-icon.png
new file mode 100644
index 0000000..9d46c37
Binary files /dev/null and b/assets/meet-your-host/host-icon.png differ
diff --git a/assets/meet-your-host/host.png b/assets/meet-your-host/host.png
new file mode 100644
index 0000000..b6a52f8
Binary files /dev/null and b/assets/meet-your-host/host.png differ
diff --git a/assets/membership-growth/growth-icon.png b/assets/membership-growth/growth-icon.png
new file mode 100644
index 0000000..92205c9
Binary files /dev/null and b/assets/membership-growth/growth-icon.png differ
diff --git a/assets/schedule/schedule-bubble.png b/assets/schedule/schedule-bubble.png
new file mode 100644
index 0000000..ef0f754
Binary files /dev/null and b/assets/schedule/schedule-bubble.png differ
diff --git a/assets/schedule/schedule-icon.png b/assets/schedule/schedule-icon.png
new file mode 100644
index 0000000..2013989
Binary files /dev/null and b/assets/schedule/schedule-icon.png differ
diff --git a/assets/schedule/schedule-speaker.png b/assets/schedule/schedule-speaker.png
new file mode 100644
index 0000000..c21c89a
Binary files /dev/null and b/assets/schedule/schedule-speaker.png differ
diff --git a/assets/speakers/bg1.png b/assets/speakers/bg1.png
new file mode 100644
index 0000000..96813c1
Binary files /dev/null and b/assets/speakers/bg1.png differ
diff --git a/assets/speakers/bg2.png b/assets/speakers/bg2.png
new file mode 100644
index 0000000..05ecc72
Binary files /dev/null and b/assets/speakers/bg2.png differ
diff --git a/assets/speakers/speaker-bubble.png b/assets/speakers/speaker-bubble.png
new file mode 100644
index 0000000..bcf2f26
Binary files /dev/null and b/assets/speakers/speaker-bubble.png differ
diff --git a/assets/speakers/speaker1.png b/assets/speakers/speaker1.png
new file mode 100644
index 0000000..658dee5
Binary files /dev/null and b/assets/speakers/speaker1.png differ
diff --git a/assets/speakers/speaker2.png b/assets/speakers/speaker2.png
new file mode 100644
index 0000000..7904c84
Binary files /dev/null and b/assets/speakers/speaker2.png differ
diff --git a/assets/speakers/speaker3.png b/assets/speakers/speaker3.png
new file mode 100644
index 0000000..ca9c2d2
Binary files /dev/null and b/assets/speakers/speaker3.png differ
diff --git a/assets/tickets/card-bg.png b/assets/tickets/card-bg.png
new file mode 100644
index 0000000..5c2fef8
Binary files /dev/null and b/assets/tickets/card-bg.png differ
diff --git a/assets/tickets/tickets-icon.png b/assets/tickets/tickets-icon.png
new file mode 100644
index 0000000..b25405e
Binary files /dev/null and b/assets/tickets/tickets-icon.png differ
diff --git a/assets/what-to-expect/people-collage.png b/assets/what-to-expect/people-collage.png
new file mode 100644
index 0000000..1c85b50
Binary files /dev/null and b/assets/what-to-expect/people-collage.png differ
diff --git a/enqueue.php b/enqueue.php
new file mode 100644
index 0000000..8a91cfd
--- /dev/null
+++ b/enqueue.php
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
Sept 22nd - 24th 2025 / Newcastle, UK
+
RETAIN - The Membership Growth Conference
+
+
+ 00
+ Days
+
+
+ 00
+ Hours
+
+
+ 00
+ Minutes
+
+
+ 00
+ Seconds
+
+
+
+
+
+
+
+
+
+
+
Ready to accelerate your membership growth?
+
+
+
+ A one of a kind event for membership site owners who want to increase their membership growth in 2025 and beyond.
+
+
+
+ Hear from successful membership owners and industry experts on the strategies and tactics that are working for them, discover future trends and new ideas, ask questions and connect with other membership site owners from around the world over the course of 2 days in Newcastle upon Tyne, UK.
+
+
+ With a mix of keynotes, power sessions, panels and more it’s all about providing you with actionable content that you can implement in your own membership to take it to the next level. With strictly no fluff, theory or pitching!
+
+
+ Retain is the only live event dedicated entirely to growing your online membership.
+
+
+ It’s an event for membership site owners, by membership site owners.
+
+ Are you in?
+
+
+
+
+
+
+
+
+
+
+
What you can expect
+
+ 2 action packed days of membership goodness with talks and panels on a variety of membership topics. Plus plenty of time for talking with other membership site owners too – because lets be honest, the conversations you have and ideas you get from the other people in the room are often the best bit of attending a conference!
+
+
+
+
What you can expect
+
+ 2 action packed days of membership goodness with talks and panels on a variety of membership topics. Plus plenty of time for talking with other membership site owners too – because lets be honest, the conversations you have and ideas you get from the other people in the room are often the best bit of attending a conference!
+
+
+
+
What you can expect
+
+ 2 action packed days of membership goodness with talks and panels on a variety of membership topics. Plus plenty of time for talking with other membership site owners too – because lets be honest, the conversations you have and ideas you get from the other people in the room are often the best bit of attending a conference!
+
+
+
+
+
+
+
+
+
+
+
Check out highlights of our 2019 event:
+
+
+
+
+
+
+
+
+
+
+
+
+
Meet your host for Retain 2025
+
+
+
+
+
+
+
+
+ Mike Morrison
+
+ Howdy, I’m Mike Morrison, founder of the “Membership Geeks”
+
+
+ I’ve spent years guiding the growth of thousands of memberships, e-learning businesses and online communities.
+
+
+ With 20+ years in the online marketing and web development industry, we’ve been the driving force behind a multitude of 6 and 7 figure membership businesses in a diverse range of industries – from weight loss to coaching to executive training to bass guitar – and we have a proven track record of helping great clients to achieve fantastic results.
+
+
+ In 2015 I decided to take all of that knowledge and experience and use it to help entrepreneurs and small business owners to achieve success with membership sites on a global scale, and so created Membership Academy which has now helped over 11,000 membership site owners.
+
+
+ I’ll be leading the charge at Retain 2025 providing training throughout both days on the latest membership growth tactics and strategies, and sharing insights from our work with countless successful memberships.
+
+ But I’m not coming alone…
+
+
+
+
+
+
+
+
+
+
You'll also learn from expert guests including:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Buy your ticket
+
+
+
+
Join us on September 22nd - 24th 2025 in Newcastle-Upon-Tyne, England for THE membership growth event that you simply can’t afford to miss.
+
+
+
+ Don’t forget: members of Membership Academy receive a discount on their ticket price!
+
+
+
+
+ PLUS take advantage of Earlybird pricing if you buy your ticket today!
+
+
+
+
+
+
+
£345
+
+
Earlybird (non-members)
+
+
+ Save £150
+ Access to all sessions
+ Lunch & refreshments provided
+ Academy member discount
+
+
BUY NOW
+
+
+
+
+
+
+
£245
+
+
+ Save £250
+ Access to all sessions
+ Lunch & refreshments provided
+ Academy member discount
+
+
BUY NOW
+
+
+
+
+
+
+
+
+
+
+
+
+
Location
+
+
+
+
Hilton Newcastle Gateshead
+
Bottle Bank, Gateshead NE8 2AR
+
Newcastle Airport (8 miles)
+
Central Station (1.3 miles)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Frequently Asked Questions
+
+
+
+
+
WHATS INCLUDED IN THE TICKET PRICE?
+
+
+ Your completed registration includes the following:
+
+
+ Access to all speaker presentations and panels throughout both days of the conference
+ Breakfast, lunch and refreshments on both days
+ Complimentary Wifi access in the event area
+ And a few special surprises…
+
+ Note: Hotel, airfare and other travel expenses are not included in the ticket price.
+
+
+
+
ARE THERE ANY DISCOUNTS FOR STUDENTS OR CHARITIES?
+
+
+ Your completed registration includes the following:
+
+
+ Access to all speaker presentations and panels throughout both days of the conference
+ Breakfast, lunch and refreshments on both days
+ Complimentary Wifi access in the event area
+ And a few special surprises…
+
+ Note: Hotel, airfare and other travel expenses are not included in the ticket price.
+
+
+
+
CAN I BUY A TICKET TO JUST ONE OF THE DAYS OF THE EVENT?
+
+
+ Your completed registration includes the following:
+
+
+ Access to all speaker presentations and panels throughout both days of the conference
+ Breakfast, lunch and refreshments on both days
+ Complimentary Wifi access in the event area
+ And a few special surprises…
+
+ Note: Hotel, airfare and other travel expenses are not included in the ticket price.
+
+
+
+
WHAT IS YOUR REFUND POLICY?
+
+
+ Your completed registration includes the following:
+
+
+ Access to all speaker presentations and panels throughout both days of the conference
+ Breakfast, lunch and refreshments on both days
+ Complimentary Wifi access in the event area
+ And a few special surprises…
+
+ Note: Hotel, airfare and other travel expenses are not included in the ticket price.
+
+
+
+
ARE MEALS PROVIDED?
+
+
+ Your completed registration includes the following:
+
+
+ Access to all speaker presentations and panels throughout both days of the conference
+ Breakfast, lunch and refreshments on both days
+ Complimentary Wifi access in the event area
+ And a few special surprises…
+
+ Note: Hotel, airfare and other travel expenses are not included in the ticket price.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Schedule
+
+
+
+
+
+ Day 1
+ 22/09/2025
+
+
+ Day 2
+ 23/09/2025
+
+
+
+
+
+ Day 1
+ 22/09/2025
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
No schedule available for Day 1.
+
+
+
+
+
+ Day 2
+ 23/09/2025
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
No schedule available for Day 2.
+
+
+
+
+
+
+
diff --git a/functions.php b/functions.php
new file mode 100644
index 0000000..166e774
--- /dev/null
+++ b/functions.php
@@ -0,0 +1,27 @@
+ __('Primary Menu', 'retain-theme'),
+ ));
+}
+add_action('after_setup_theme', 'retain_theme_setup');
+
+// Include enqueue functions
+require_once get_template_directory() . '/enqueue.php';
+
+// Include ACF fields
+require_once get_template_directory() . '/inc/acf/speaker-fields.php';
+require_once get_template_directory() . '/inc/acf/schedule-fields.php';
diff --git a/inc/acf/schedule-fields.php b/inc/acf/schedule-fields.php
new file mode 100644
index 0000000..7664e68
--- /dev/null
+++ b/inc/acf/schedule-fields.php
@@ -0,0 +1,122 @@
+ 'group_schedule',
+ 'title' => 'Schedule Section',
+ 'fields' => array(
+ // Day 1 Schedule
+ array(
+ 'key' => 'field_schedule_day_1',
+ 'label' => 'Day 1 Schedule',
+ 'name' => 'schedule_day_1',
+ 'type' => 'repeater',
+ 'instructions' => 'Add schedule for Day 1',
+ 'required' => 0,
+ 'min' => 0,
+ 'max' => 0,
+ 'layout' => 'block',
+ 'button_label' => 'Add Session',
+ 'sub_fields' => array(
+ array(
+ 'key' => 'field_day1_time',
+ 'label' => 'Time',
+ 'name' => 'time',
+ 'type' => 'text',
+ 'required' => 1,
+ ),
+ array(
+ 'key' => 'field_day1_session',
+ 'label' => 'Session',
+ 'name' => 'session',
+ 'type' => 'text',
+ 'required' => 1,
+ ),
+ array(
+ 'key' => 'field_day1_speaker_name',
+ 'label' => 'Speaker Name',
+ 'name' => 'speaker_name',
+ 'type' => 'text',
+ 'required' => 0,
+ ),
+ array(
+ 'key' => 'field_day1_speaker_photo',
+ 'label' => 'Speaker Photo',
+ 'name' => 'speaker_photo',
+ 'type' => 'image',
+ 'required' => 0,
+ 'return_format' => 'array',
+ 'preview_size' => 'medium',
+ 'library' => 'all',
+ ),
+ ),
+ ),
+ // Day 2 Schedule
+ array(
+ 'key' => 'field_schedule_day_2',
+ 'label' => 'Day 2 Schedule',
+ 'name' => 'schedule_day_2',
+ 'type' => 'repeater',
+ 'instructions' => 'Add schedule for Day 2',
+ 'required' => 0,
+ 'min' => 0,
+ 'max' => 0,
+ 'layout' => 'block',
+ 'button_label' => 'Add Session',
+ 'sub_fields' => array(
+ array(
+ 'key' => 'field_day2_time',
+ 'label' => 'Time',
+ 'name' => 'time',
+ 'type' => 'text',
+ 'required' => 1,
+ ),
+ array(
+ 'key' => 'field_day2_session',
+ 'label' => 'Session',
+ 'name' => 'session',
+ 'type' => 'text',
+ 'required' => 1,
+ ),
+ array(
+ 'key' => 'field_day2_speaker_name',
+ 'label' => 'Speaker Name',
+ 'name' => 'speaker_name',
+ 'type' => 'text',
+ 'required' => 0,
+ ),
+ array(
+ 'key' => 'field_day2_speaker_photo',
+ 'label' => 'Speaker Photo',
+ 'name' => 'speaker_photo',
+ 'type' => 'image',
+ 'required' => 0,
+ 'return_format' => 'array',
+ 'preview_size' => 'medium',
+ 'library' => 'all',
+ ),
+ ),
+ ),
+ ),
+ 'location' => array(
+ array(
+ array(
+ 'param' => 'page_template',
+ 'operator' => '==',
+ 'value' => 'front-page.php',
+ ),
+ ),
+ ),
+ 'menu_order' => 0,
+ 'position' => 'normal',
+ 'style' => 'default',
+ 'label_placement' => 'top',
+ 'instruction_placement' => 'label',
+ 'hide_on_screen' => '',
+));
+
+endif;
+?>
diff --git a/inc/acf/speaker-fields.php b/inc/acf/speaker-fields.php
new file mode 100644
index 0000000..2ec81b9
--- /dev/null
+++ b/inc/acf/speaker-fields.php
@@ -0,0 +1,74 @@
+ 'group_speakers',
+ 'title' => 'Speakers Section',
+ 'fields' => array(
+ array(
+ 'key' => 'field_speakers',
+ 'label' => 'Speakers',
+ 'name' => 'speakers',
+ 'type' => 'repeater',
+ 'instructions' => 'Add speakers here',
+ 'required' => 0,
+ 'min' => 0,
+ 'max' => 0,
+ 'layout' => 'block',
+ 'button_label' => 'Add Speaker',
+ 'sub_fields' => array(
+ array(
+ 'key' => 'field_speaker_image',
+ 'label' => 'Speaker Image',
+ 'name' => 'speaker_image',
+ 'type' => 'image',
+ 'required' => 1,
+ 'return_format' => 'array',
+ 'preview_size' => 'medium',
+ 'library' => 'all',
+ ),
+ array(
+ 'key' => 'field_speaker_first_name',
+ 'label' => 'Speaker Name',
+ 'name' => 'speaker_name',
+ 'type' => 'text',
+ 'required' => 1,
+ ),
+ array(
+ 'key' => 'field_speaker_last_name',
+ 'label' => 'Speaker Last Name',
+ 'name' => 'speaker_last_name',
+ 'type' => 'text',
+ 'required' => 1,
+ ),
+ array(
+ 'key' => 'field_speaker_role',
+ 'label' => 'Speaker Role',
+ 'name' => 'speaker_role',
+ 'type' => 'text',
+ 'required' => 1,
+ )
+ )
+ )
+ ),
+ 'location' => array(
+ array(
+ array(
+ 'param' => 'page_template',
+ 'operator' => '==',
+ 'value' => 'front-page.php', // The ACF field group will only appear on the front-page.php template
+ ),
+ ),
+ ),
+ 'menu_order' => 0,
+ 'position' => 'normal',
+ 'style' => 'default',
+ 'label_placement' => 'top',
+ 'instruction_placement' => 'label',
+ 'hide_on_screen' => '',
+));
+
+endif;
diff --git a/inc/js/collapsible.js b/inc/js/collapsible.js
new file mode 100644
index 0000000..6440839
--- /dev/null
+++ b/inc/js/collapsible.js
@@ -0,0 +1,35 @@
+document.addEventListener('DOMContentLoaded', function() {
+ var coll = document.getElementsByClassName("collapsible");
+
+ for (var i = 0; i < coll.length; i++) {
+ // Wrap the existing text inside a span
+ var span = document.createElement("span");
+ span.classList.add("toggle-icon"); // Add class for styling
+ span.textContent = "+";
+
+ // Move the existing text into another span for separation
+ var textSpan = document.createElement("span");
+ textSpan.classList.add("collapsible-text");
+ textSpan.textContent = coll[i].innerHTML;
+
+ // Clear the button content and append spans
+ coll[i].innerHTML = "";
+ coll[i].appendChild(span);
+ coll[i].appendChild(textSpan);
+
+ // Add click event
+ coll[i].addEventListener("click", function() {
+ this.classList.toggle("active");
+ var content = this.nextElementSibling;
+ var icon = this.querySelector(".toggle-icon");
+
+ if (content.style.display === "block") {
+ content.style.display = "none";
+ icon.textContent = "+"; // Change to +
+ } else {
+ content.style.display = "block";
+ icon.textContent = "-"; // Change to -
+ }
+ });
+ }
+});
\ No newline at end of file
diff --git a/inc/js/countdown.js b/inc/js/countdown.js
new file mode 100644
index 0000000..f497105
--- /dev/null
+++ b/inc/js/countdown.js
@@ -0,0 +1,67 @@
+class EventCountdown {
+ constructor(eventDate, elementIds) {
+ this.eventDate = new Date(eventDate).getTime();
+ this.elements = {
+ days: document.getElementById(elementIds.days),
+ hours: document.getElementById(elementIds.hours),
+ minutes: document.getElementById(elementIds.minutes),
+ seconds: document.getElementById(elementIds.seconds),
+ container: document.getElementById(elementIds.container)
+ };
+ this.countdownTimer = null;
+ }
+
+ calculateTimeRemaining() {
+ const now = new Date().getTime();
+ const distance = this.eventDate - now;
+
+ return {
+ days: Math.floor(distance / (1000 * 60 * 60 * 24)),
+ hours: Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)),
+ minutes: Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)),
+ seconds: Math.floor((distance % (1000 * 60)) / 1000),
+ distance: distance
+ };
+ }
+
+ padNumber(number) {
+ return String(number).padStart(2, '0');
+ }
+
+ updateDisplay(timeRemaining) {
+ this.elements.days.textContent = this.padNumber(timeRemaining.days);
+ this.elements.hours.textContent = this.padNumber(timeRemaining.hours);
+ this.elements.minutes.textContent = this.padNumber(timeRemaining.minutes);
+ this.elements.seconds.textContent = this.padNumber(timeRemaining.seconds);
+ }
+
+ start() {
+ const update = () => {
+ const timeRemaining = this.calculateTimeRemaining();
+
+ if (timeRemaining.distance < 0) {
+ clearInterval(this.countdownTimer);
+ this.elements.container.innerHTML = 'Event has started!';
+ return;
+ }
+
+ this.updateDisplay(timeRemaining);
+ };
+
+ update(); // Initial call
+ this.countdownTimer = setInterval(update, 1000);
+ }
+}
+
+// Initialize countdown when DOM is loaded
+document.addEventListener('DOMContentLoaded', () => {
+ const countdown = new EventCountdown('September 22, 2025 00:00:00', {
+ days: 'days',
+ hours: 'hours',
+ minutes: 'minutes',
+ seconds: 'seconds',
+ container: 'countdown'
+ });
+
+ countdown.start();
+});
\ No newline at end of file
diff --git a/inc/js/navigation.js b/inc/js/navigation.js
new file mode 100644
index 0000000..83717aa
--- /dev/null
+++ b/inc/js/navigation.js
@@ -0,0 +1,23 @@
+document.addEventListener('DOMContentLoaded', function() {
+
+ console.log('Navigation JS loaded');
+
+ const menuToggle = document.querySelector('.menu-toggle');
+ const menuModal = document.querySelector('#menu-modal');
+ const menuClose = document.querySelector('.menu-close');
+
+ menuToggle.addEventListener('click', function() {
+ menuModal.classList.toggle('active');
+ });
+
+ menuClose.addEventListener('click', function() {
+ menuModal.classList.remove('active');
+ });
+
+ // Close the modal when clicking outside of it
+ window.addEventListener('click', function(event) {
+ if (event.target === menuModal) {
+ menuModal.classList.remove('active');
+ }
+ });
+});
\ No newline at end of file
diff --git a/inc/js/schedule-tabs.js b/inc/js/schedule-tabs.js
new file mode 100644
index 0000000..7853333
--- /dev/null
+++ b/inc/js/schedule-tabs.js
@@ -0,0 +1,37 @@
+document.addEventListener('DOMContentLoaded', function() {
+ function openTab(evt, tabName) {
+ var i, tabcontent, tabbuttons;
+ tabcontent = document.getElementsByClassName("tab-content");
+ for (i = 0; i < tabcontent.length; i++) {
+ tabcontent[i].style.display = "none";
+ }
+ tabbuttons = document.getElementsByClassName("tab-button");
+ for (i = 0; i < tabbuttons.length; i++) {
+ tabbuttons[i].className = tabbuttons[i].className.replace(" active", "");
+ }
+ document.getElementById(tabName).style.display = "block";
+ evt.currentTarget.className += " active";
+ }
+
+ // Attach the openTab function to the global scope
+ window.openTab = openTab;
+
+ // Check viewport width and apply default tab only for screens 768px and above
+ if (window.innerWidth >= 768) {
+ document.querySelector('.tab-button.active').click();
+ }
+
+ // Re-evaluate on window resize
+ window.addEventListener('resize', function() {
+ if (window.innerWidth < 768) {
+ // Show all tabs on small screens
+ var tabcontent = document.getElementsByClassName("tab-content");
+ for (var i = 0; i < tabcontent.length; i++) {
+ tabcontent[i].style.display = "block";
+ }
+ } else {
+ // Trigger the first tab by default on larger screens
+ document.querySelector('.tab-button.active').click();
+ }
+ });
+});
diff --git a/index.php b/index.php
new file mode 100644
index 0000000..49cac2a
--- /dev/null
+++ b/index.php
@@ -0,0 +1,17 @@
+
+
+