Elementor Website Course Logo

The Elementor Website Course

Learn the Tool, Master the Web.

Optimise with our Super Elementor Website Course.

Unlock your skills with techniques, WordPress best practices, and mindful preparation to take your designs to a new level.

- Instant Access
- 12 hours+ Videos
- 118 Lessons
- Using Elementor Pro
- Free Templates
- Exclusive Coupons
- Ever-Expanding
- Taught by Imran Siddiq

Is this Web Design Course right for you?

In the fast-paced digital world, mastering efficient website building will be your secret weapon.

Harness your potential with this Elementor Website Course, and say ‘goodbye’ to building websites incorrectly.

Attract and captivate clients with your stunning, high-speed website creations. Join us, and lead the digital charge with confidence!

Join the Ride

$

147

ReducedPrices will be shown for some Regions inside of the Cart.

Normal Price: $197

One-Time Cost

Access to Future Modules

118 Videos covering 12+ Hours.

13 Modules split over 118 lessons

Notes supporting each lesson

Website to be built > Demo

Full Template Kit of Demo provided

Free Full Ebook – How to Start a Web Design Business (worth $49)

‘Course’ Exclusive Coupons for useful Tools

Roadmap for future lessons (no added cost) > Visit

Free Tools to help you with responsive design > Visit

Free Support Group > Come Over Now!

Course Breakdown

Module 1: Pre Build Resources

Point of the Website

SiteMap

Logo and Images

Compressing Images

Colour Palettes & Fonts

Compressing Fonts

Written Content

Wireframes

 

Module 2: WordPress Set-Up

Domain + Hosting

WordPress Settings

Plugins

Media Library

Add New Page

 

Module 3: Elementor Settings

Elementor Interface

Elementor Widgets

Adding SVG

Global Colours

Global Fonts

 

Module 4: Elementor First Steps

Flex Box Containers

Add Page to Menu

Check the Page Score

Header Template

Footer Template Placement


Module 5: The Home Page

Hero Banner

Adding an Introduction

Adding Services

Additional Information

Portfolio Container

Quote Container

Contact

Header Sticky

Module 6: Other Pages Build

Services Page

About Page

Contact Page

Privacy & Cookies Policy

Menu Update

Header Refine

Links & Anchor Links

Footer Template

404 Template

 

Module 7: Blog Posts

Add WordPress Posts

Add Custom Fields

Loop Grid Post Archive

Taxonomy Filter

Query

Blog Page

Single Post Template


Module 8: GridBuilder WP

Using the GridBuilder Plugin

Creating Filters

Adding to the Loop Grid


Module 9: Sidebar for Posts

Setting up the Template Layout

Adding the Sidebar Contents

Making the Sidebar Sticky


Module 10: Custom Posts & Fields

Creating Custom Posts

Adding Custom Taxonomies

Adding Custom Fields

Using the Custom Fields

Loop Grid with the Custom Fields

Single Posts with the Custom Fields

Adding the Sidebar Contents

Module 11: Pop Ups & Off Canvas Menus

Creating Pop Ups

Setting Triggers for Pop Ups

Activating Pop Ups

Creating Off Canvas Menus

Opening Off Canvas Menus on the Mobile

Opening a 2nd Pop Up

 

Module 12: WooCommerce

WooCommerce Settings

Payment Gateways Set Up

Simple & Variable Products

Shop Templates

Ways to Add Shop Filtering 

Single Product Templates

Refining the Cart, Checkout, Account

Adding Woo Items to the Header

 

Module 13: SEO and RankMath

SEO Keywords Research

Setting Up RankMath

Boosting Page SEO

Boosting Posts SEO

Boosting Products SEO

Connecting Google Search Console

Connecting Google Analytics

SiteMap Submissions

Instant Indexing

Time to join the Elementor Website Course!

My YouTube Tutorials cover WordPress and Elementor however they’re missing extra notes and tips. That changes with this Elementor Website Course.

Boost Your Business: Learn to build websites faster and better, giving your business the edge it deserves.

Master Elementor: Turn designs into functional websites.

Stay Ahead of the Competition: Leave your rivals in the dust by delivering top-notch websites quicker than ever before.

Boost Responsive Optimisation: Create websites that look stunning and function flawlessly from smartphones to desktops.

Proven Techniques: Benefit from proven methods of a seasoned expert, saving you time and effort on trial-and-error.

Profile Image of Imran Siddiq, the Course Leader of Web Squadron

I'm a bit of a maverick in the world of web design education.

Let's blend expertise, tips, and bring innovative approaches to deliver solutions.

You won't just be learning a tool; you're on a journey of creativity. Ready to launch?"

Questions about the Course

The course is built with Elementor Pro, and we recommend that you obtain Elementor from here.

You’ll need Elementor Free and Pro to join in the course, or to use the Template Kit.

Several other Free plugins are used in the course for optimisation, however they are optional. We do not use any Elemenor Addons as we prefer to keep plugin overheads to a minimum.

Indeed yes, when the changes or updates from Elementor affect the production of the website.

This super course uses the Flexbox Container, rather than sections, which is the default layout with Elementor since September 2023.

We only use Flexbox Container in the super course, but don’t worry as we cover it assuming that you have no experience.

We would rather teach you all of the basics as if you’ve never used WordPress or Elementor before.

We stress the importance of responsiveness for different screen sizes and we’ll cover using Font Clamp with a free tool.

We’ll also encourage good practice for many areas of web design to improve mobile responsiveness, image sizes, font compression, and page speed optimisation to improve user experience.

He first worked on websites in 2004, and moved to WordPress when it burst on the scene. 

Due to his full-time career in NHS Analytics, he produced websites as a side-hustle until 2019. Eventually the bug stuck, and he retired from the NHS in January 2022 to work full-time on the Web Agency.

Ever-evolving with tools over the years, he settled on Elementor in 2019. Imran also dabbles with Bricks Builder, and is always on the lookout for cost-effective solutions.

Never short of tutorials or tips, Imran provides a valuable service to web designers and businesses and anyone else who wants to ‘Make a Difference!’

It will be presented within this website without taking you to another LMS or Teaching platform.

The course is delivered via videos, notes (containing additional guidance and values where relevant).

You can jump round the course without being restricted or having to watch in a set order.

We don’t have a separate site or community as I want you to be part of a wider group – regardless of purchasing this course or not.

Jump over to our Web Squadron Facebook Group.

We don’t offer refunds due to the electronic nature of the course.

We would ask that you understand the time and effort that has gone into the course, and only request a refund where necessary. Funds from the course go towards investing to ensure we keep producing fantastic content for our community.

Not when you have the right tutors, lessons, and guidance.

Every tool has a learning curve, but once you are shown how to get the most out of the basics, and to then delve into maximising the impact, you’ll be glad that you decided to give it a go.

Elementor is a valuable tool especially those who want to create websites quickly and efficiently.

If you’re looking to improve your web design capabilities and work with WordPress websites, learning Elementor is a worthwhile investment of your time and effort.

What do you think about Web Squadron?

You have a gift for explaining complex concepts in an easy-to-understand manner.

– Harish Kumar

Really outstanding support and service. Blown away by his advice and  delivery!

– Mark Doughty

Followed your steps on mobile page speeds and now now have 100% performance.

– Pete Butler

You’re the 1st person I’ve ever given a super thanks to. 

– Shane Baker

Thanks for this! It’s amazing how you help us all with Elementor.

– Destizz

Think I have become addicted to your educational videos.

– Nayan Ponz

They’re wonderful. They’re been fantastic and gave honest advice to help my business.

– Leenisha

I just found this tutorial video and wow! Such a big help and so much terrific information.

– Shelley Burleson

I. Am. Blown. Away. WOW! I keep bookmarking your content.

– Sam

The Fonts Pack

Last Updated Saturday 29 June 2024

Woff2 Fonts Bundle

Google Fonts fetching can breach GDPR, and can cause font swapping, cumulative layout shifts, and performance hits. We recommend using Woff2 Font Files as they can be 20% of the size of a standard ttf file.

12 commonly used Woff2 fonts are provided below to upload to Elementor’s Custom Fonts. 

Only upload the variations that you intend to use.

1) Unzip the File before uploading to Elementor > Custom Fonts.

Add Woff2 directly to Media Library

This Code Snippet allows you to add Woff2 fonts to your library without having to add via the Custom Fonts Upload area. This snippet is available inside the ‘Settings’ Pack.

Take a backup before adding.

				
					function custom_mime_types($mimes) {
    $mimes['woff'] = 'font/woff';
    $mimes['woff2'] = 'font/woff2';
    return $mimes;
}
add_filter('upload_mimes', 'custom_mime_types');

				
			

Font Clamp Formulas and CSS Standard Sizes

Making your fonts responsive (shrinking and growing) based on screen resolution widths removes the need to modify fonts for many breakpoints.

Use the Clamp Tools on the Tools Page.

Below is CSS that can be added to Any Page > Site Settings > Custom CSS – that provides decent sizes to help your styles. (The example image is not to scale).

This provides pre-built clamp formulas for Headings and Text, as well as sizes for #hero (if you decided to use separate sizes for a container with the id hero).

				
					/* FONT CLAMP -- Min Width 400p -- Max Width 1200px */

/* Set the root font size to 100% to be better for Web Accessibility*/
html {font-size: 100%;}

/* If you prefer to set it to 10px for easier rem calculations */
html {font-size: 62.5%;} /* 1rem = 10px */


/* Add a title to a container's css id eg:'hero' and then use #hero to target that container.
#hero h1 {font-size: clamp(2rem, 1.25rem + 3vw, 3.5rem);
font-weight: 800;}

#hero h2 {font-size: clamp(2rem, 1.25rem + 3vw, 3.5rem);
font-weight: 800;}

#hero p {font-size: clamp(2rem, 1.25rem + 3vw, 3.5rem);
font-weight: 800;}
*/

h1 {font-size: clamp(2.5rem, 1.75rem + 3vw, 4rem);
font-weight: 900;} /* 40px to 64px */

h2 {font-size: clamp(2rem, 1.25rem + 3vw, 3.5rem);
font-weight: 800;} /* 32px to 56px */

h3 {font-size: clamp(1.75rem, 1.125rem + 2.5vw, 3rem);
font-weight: 700;} /* 28px to 48px */

h4 {font-size: clamp(1.5rem, 1rem + 2vw, 2.5rem);
font-weight: 500;} /* 24px to 40px */

h5 {font-size: clamp(1.25rem, 0.875rem + 1.5vw, 2rem);
font-weight: 500;} /* 20px to 32px */

h6 {font-size: clamp(1rem, 0.75rem + 1vw, 1.5rem);
font-weight: 500;} /* 16px to 28px */

body {font-size: clamp(1rem, 0.875rem + 0.5vw, 1.25rem);
font-weight: normal;} /* 16px to 20px */

p {font-size: clamp(1rem, 0.875rem + 0.5vw, 1.25rem);
font-weight: normal;}/* 16px to 20px */

				
			
				
					/* Remove Extra Spacing from the bottom of Text Editors*/

.elementor-widget-text-editor p:last-child{ margin-bottom:0px;}
				
			

The Plugins Pack

Last Updated Saturday 29 June 2024

Standard Elementor Website

These are part of my current stack. Take a backup before installing new plugins. All links are to their WordPress Repository, except for Elementor Pro (Affiliate Link). The Hello Theme is advised to reduce unnecessary features. 

Alternate solutions are shown (i, ii, iii) depending on your requirements.

1) Elementor Free – Standard Page Builder – https://wordpress.org/plugins/elementor/

2) Elementor Pro – Advanced Plan to get all of the Pro Widgets – Get Elementor Pro

3) WP Fastest Cache – (Free) for caching – https://wordpress.org/plugins/wp-fastest-cache/

4) PhastPress – (Free) Performance Boosting – https://wordpress.org/plugins/phastpress/

5) Rank Math SEO – (Free) SEO Tool – https://wordpress.org/plugins/seo-by-rank-math/

6) Code Snippets – (Free) Add improvements and reduce using plugins – https://wordpress.org/plugins/code-snippets/

7) Malcare – (Free) Malware Protection and Site Security – https://wordpress.org/plugins/malcare-security/

8) Headers Security Advanced & HSTS WP – (Free) Secure your Headers – https://wordpress.org/plugins/headers-security-advanced-hsts-wp/

9) Cookiebot – (Free) GDPR and International – https://wordpress.org/plugins/cookiebot/ 

10) Gridbuilder (OPTIONAL) – (Paid) Advanced Filtering – https://wpgridbuilder.com/

11) Advanced Custom Fields (OPTIONAL) – (Free) Additional Post Types and Fields – https://wordpress.org/plugins/advanced-custom-fields/

12) WP Sweep (OPTIONAL) – (Free) Clean Revisions and Transients, and Optimise Databases – This can be used when required and then uninstalled – https://wordpress.org/plugins/wp-sweep/

13-i) UpdraftPlus (OPTIONAL) – (Free) Cloud-based Backups – https://wordpress.org/plugins/updraftplus/

13-ii) All in One Migration (OPTIONAL)  – (Free) for Quick Exports & Imports. (Paid) for Scheduled Backups to OneDrive – https://wordpress.org/plugins/all-in-one-wp-migration/

14) SiteOrigns CSS (OPTIONAL) – (Free) Help to write CSS Codes – https://wordpress.org/plugins/so-css/

Standard E-Commerce Elementor Website

Plugins listed below are in addition to the Plugins from the Standard Elementor section.

I recommend that you set up logins and confirm verification with Payment Gateways a week before building to reduce potential delays.

1) WooCommerce – (Free) E-Commerce – https://wordpress.org/plugins/woocommerce/

2) WooCommerce PayPal Payments – (Free) –  https://wordpress.org/plugins/woocommerce-paypal-payments/

3) Stripe Payment Plugin for WooCommerce – (Free) Better options than the standard WooPayments Plugin – https://wordpress.org/plugins/payment-gateway-stripe-and-woocommerce-integration/

4) Gridbuilder (OPTIONAL) – (Paid) Advanced Filtering – https://wpgridbuilder.com/

5) Advanced Custom Fields (OPTIONAL) – (Free) Additional Post Types and Fields – https://wordpress.org/plugins/advanced-custom-fields/

6) PDF Invoices & Packing Slips for WooCommerce (OPTIONAL) – (Free) Auto create and send to customers –  https://wordpress.org/plugins/woocommerce-pdf-invoices-packing-slips/

7) Page Restrict for WooCommerce (OPTIONAL) – (Free) Lock Pages until a Product is purchased – https://wordpress.org/plugins/page-restrict-for-woocommerce/

The Settings Pack - WordPress

Last Updated Saturday 29 June 2024

WordPress General Settings

1) Set the Site Title (or go to WordPress Dashboard > Appearance > Customize).

2) Set the Site Icon (or go to WordPress Dashboard > Appearance > Customize).

3) Ensure the Address/Site URL both begin with https:// (If you don’t have a valid SSL Certificate, then check with your host).

4) Ensure the Admin Email Address is correct.

WordPress Reading Settings

This step can be left until a Homepage or a Landing Page has been created.

Return here to set the first page to be loaded when a user enters your parent domain.

WordPress Discussion Settings

The items here are subjective to if;

1) You permit comments to be added, and

2) You will moderate activity and remove spam.

Within the ‘Course’, we will advise on disabling Comments for particular Posts and Pages.

Inside of the ‘Settings Pack’, you will find the Snippets Bundle with a Code Snippet to fully disable comments on all Posts and Pages.

WordPress Media Settings

When images are added to the Media Library, multiple versions may be created in your wp-uploads folder.

1) Images should be uploaded as a webp format. We show how to convert PNG/JPEG within the ‘Course’.

2) Images should be reasonably sized to the maximum size required on the site. Do not upload an image that is 1920x 1080 if it will only be 300px wide on a site.

I leave the Thumbnail Size as 150×150, and set the others to be 0. 

Inside of the ‘Settings Pack’, you will find the Snippets Bundle with a Code Snippet to ‘future-proof’ prevent duplicate images being created in your database.

WordPress Permalink Settings

Set the format of the links that will appear for Posts, Pages and Products.

I recommend ‘Post Name’ especially if you care about SEO and Keyword Marketing.

Inside of the ‘Settings Pack’, you will find the Snippets Bundle with a Code Snippet to set the Permalink to always stay set to prevent someone modifying it.

The Settings Pack - Elementor

Last Updated Saturday 29 June 2024

Elementor General Settings

1) Posts & Pages should be selected for Post Types. If you have any other Custom Posts or Products, then check them too.

2) If you will add your own Global Colours and Global Fonts – then uncheck the Default Colours and Fonts boxes.

If you will use any colours provided by your Theme, then you will want to inherit from your theme – therefor you will need to disable the Default Colours and Fonts by checking the boxes.

Also, if you will be adding Custom CSS to define colours or styles for elements, then DO Check the box.

Just to clarify – if you WILL BE be adding Custom CSS for styles – then DO CHECK the boxes.

Elementor Advanced Settings

1) Set the Switch Editor Leader Method to be Disable. Set this to be Enabled if you have issues with loading or see a white screen.

2) Set the Enable Unfiltered File Type to be Enable if you plan to upload SVG files for your logo or icons.

3) Set the Google Fonts to be Disable to prevent ‘fetching’ of fonts (a GDPR issue), and Custom Load Fonts instead (see the ‘Fonts Pack’).

4) Set Font Awesome 4 to No. If you have any issues with Icons or Symbols appearing, then set to Yes.

Elementor Performance Settings

1) Set the CSS Print Method to External File. This is more efficient for caching, however if you regularly find that the Live page loads without style applied, then set this to be Internal.

2) Optimised Page Loading should be set to Enable unless ALL images (including above the fold) are to be lazy-loaded.

3) Optimised Gutenberg Loading should be set to Enable. This improves efficiency and only loads them when they are used/present on the page.

Elementor Features Settings (Part 1)

Only Activate Features that will be used on or within your site. If they will not be used then set to Inactive.

Reasons for why I make some Inactive;

1) Landing Pages – as I build my own pages.

2) Lazy Load Background Images – as this may affect logos or some images from loading quick enough for Page Insights or Google Core Web Vitals. Note that images and videos can be set to lazy load when Editing with Elementor.

Elementor Features Settings (Part 2)

Reasons for why I make some Inactive;

1) Display Conditions – no need unless I will restrict content based on rules.

2) Menu – unless I will be using the Mega Menu.

3) Additional Custom Breakpoints – as I prefer to future-proof and build Responsively than overload my process to cater for devices.

Elementor Features Settings (Part 3)

Reasons for why I make some Inactive;

1) Default to New Theme Builder – as I find the old Templates layout easier and more efficient to manage.

2) Hell0 Theme Header & Footer – as I will build separate Header and Footer Templates.

3) Build with AI – as I prefer to build to my designs. If you require ideas or inspiration, then enable this.

4) Form Submissions – if you want to keep all submissions then make this Active: however if your forms contain file submissions such as images, movies, or PDFs then they’ll take up space in your database.

The Settings Pack - WooCommerce

Last Updated Friday 19 July 2024
Any Settings that are skipped is intentional.

General – Store Address

Add your store or business location.

If you are using MaxMind Geolocation (see later in the Integrations tab) for the ‘Default Customer Location’ then select Geolocate.

If you will not ‘Enable Taxes’ then uncheck the box.

General – Currency Options

Select the default currency.

Uncheck ‘Enable Coupons’ if no coupons will be applied.

Products – General

Ensure the Shop Page refers to the page where the shop will sit by default – BUT – because we will build with Elementor later, then this can be adjusted once the Archive template has been built. 

‘Enable Reviews’ if you will allows products to display reviews, and for customers to leave reviews.

Products – Inventory

Will you enable stock details to be displayed when a product is being viewed.

I select ‘Always Show Quantity’ when items have set inventories.

If your shop is based on Virtual or Downloadable products, then it’s okay to uncheck the ‘Manage Stock’ box.

Products – Downloadable Products

Most can be left untouched but I recommend ensuring that ‘File Download Method’ is set to Force Downloads.

‘Access Restriction’ is best set to Grant Access after Payment.

‘Filename’ strings should be made unique to protect content.

Products – Advanced

It’s fine to uncheck all except ‘Enable Table Usage’ if you will be using product attributes (example: colour attribute for a T-shirt).

Tax – Tax Options

Taxes will only be displayed when ‘Enable Taxes’ is checked form the first General tab.

If you add additional tax classes; Reduced Rate, and Zero Rate, the. additional tabs will be available. Not all rates will be required.

Tax – Standard Rates

Add necessary rates.

Tax – Reduced Rates

Add necessary rates.

Tax – Zero Rates

Add necessary rates.

Shipping – Shipping Zones

Click to add Zones.

Add names and select continents, or countries (or limit to post-codes/zip-codes).

More than 1 zone can be created.

Shipping – Shipping Zones >  Select Shipping Method

Per Zone you can then select the Shipping Methods.

Shipping – Shipping Zones > Free Shipping Method

Refine requirements.

Shipping – Shipping Zones > Flat Rate Shipping Method

Refine requirements.

Shipping – Shipping Zones > Local Pickup Shipping Method

Refine requirements.

Shipping – Shipping Zones > Shipping Methods

More than 1 Shipping Method can be set up per Zone.

Shipping – Shipping Settings

Select your preferred options.

Shipping – Classes

If you will have variation in prices based on weight or total cost, then add a Shipping Class.

Note that this not required where the shipping cost is not affected by the combined weight of all items.

Shipping – Classes –> Shipping Zone

If a Class is created, then return to the Shipping Zone tab, and ensure that the relevant price adjustments are added.

Payments

In this video, I use the standard WooPayments plugin, and Woocommerce PayPal Payments. 

If you require further options for Stripe, then instead of WooPayments, use Stripe Payment Plugin for WooCommerce (Free).

Accounts & Privacy

Allowing customers to login  to existing accounts, or to create an account during checkout is advised.

If you create a Privacy Policy page with an alternate slug then replace the [privacy_policy] referred to in the policy sections.

Emails

The brand colours and content of the emails can be adjusted, or left as default.

Integration

Add your MaxMInd License Key – Free to obtain the key – if you will use any form of geolocation for addresses or pricing.

Site Visibility

Toss a coin, and make your decision.

Advanced

There is no need to modify the pre-set page names or hooks, unless you have an alternate page that will contain the Cart and Checkout widgets.

When the Terms and Conditions page is created, then add the page name here.

Rest API

This is only required when connecting to a 3rd Party Fulfilment Centre will require API keys to be added.

Your 3rd Party Centre should have the steps and instructions to take to connect to WooCommerce. 

Webhooks

This is only required when connecting to a 3rd Party service. and you’ll be advised by the service if this step must be performed.

Your 3rd Party service should have the steps and instructions to take to connect to WooCommerce. 

WooCommerce.com Usage Tracking

Optional, but I uncheck all boxes.

Features

Create a site backup (and then export using a plugin such as All in One Migration) and test before activating HPOS – High Performance Order Storage.

The Settings Pack - Code Snippets

Last Updated Wednesday 17th July 2024

Code Snippets Bundle

The Bundle contains 22 Snippets that improve Performance of your website, and add Admin Controls. You can import them all in one go rather than copying and pasting individually.

You will need the Free Code Snippets Plugin.

Before adding New Snippets

  1. Always take a Backup
  2. Preferably Export a Full Backup
  3. Test on a Staging Site.
 

Click to download the Bundle OR Scroll down to see each individual snippet and add individually.

1) Unzip the File.

2) Go to WordPress Dashboard > Snippets > Import

3) The snippets will be added in ‘Deactivated’ form so you can manually activate them depending on your choice.

Go to Upload Files, and choose the unzipped file: elementor.code-snippets.json

Click the ‘Upload files and import’

If you are adding the Bundle again after it’s been updated with new snippets, then select the 3rd option to not import any duplicate snippets.

Then go to All Snippets and decide on which Snippets to Activate.

Activate and check one at a time.

				
					add_action( 'init', 'add_categories_to_pages' );
 /*
  * Add CATEGORIES to pages
  */
function add_categories_to_pages() {
  
  register_taxonomy_for_object_type( 'category', 'page' );
  
}
				
			
				
					// Add the Contrast Checker Menu
add_action('admin_menu', 'contrast_checker_menu');
add_action('admin_init', 'contrast_checker_settings');

function contrast_checker_menu() {
    add_options_page('Contrast Checker', 'Contrast Checker', 'manage_options', 'contrast-checker', 'contrast_checker_page');
}

function contrast_checker_settings() {
    add_settings_section('contrast_checker_section', 'Contrast Checker Settings', null, 'contrast-checker');

    add_settings_field('background_color', 'Background Color', 'background_color_callback', 'contrast-checker', 'contrast_checker_section');
    add_settings_field('text_color', 'Foreground Color', 'foreground_color_callback', 'contrast-checker', 'contrast_checker_section');

    register_setting('contrast_checker_group', 'background_color');
    register_setting('contrast_checker_group', 'text_color');
}

function background_color_callback() {
    $background_color = get_option('background_color', '#FFFFFF');
    echo '<div style="display: flex; align-items: center;"><input type="text" id="background_color" name="background_color" value="' . esc_attr($background_color) . '" class="my-color-field" style="font-size: 15px !important;" />';
    echo '<span id="background_color_hex" style="margin-left: 10px; font-size: 15px;">' . esc_attr($background_color) . '</span></div>';
}

function foreground_color_callback() {
    $foreground_color = get_option('text_color', '#000000');
    echo '<div style="display: flex; align-items: center;"><input type="text" id="text_color" name="text_color" value="' . esc_attr($foreground_color) . '" class="my-color-field" style="font-size: 15px !important;" />';
    echo '<span id="text_color_hex" style="margin-left: 10px; font-size: 15px;">' . esc_attr($foreground_color) . '</span></div>';
}

function contrast_checker_page() {
    ?>
    <div class="wrap" style="font-size: 15px; line-height: 1.2em; background-color: #ffffff; padding: 20px; border-radius: 5px;">
        <h1 style="font-size: 20px; line-height: 1.2em;">Contrast Checker</h1>
        <form method="post" action="options.php">
            <?php
            settings_fields('contrast_checker_group');
            do_settings_sections('contrast-checker');
            submit_button('Save Colors', 'primary', 'submit', true, array('style' => 'background-color: #000; font-size: 16px; font-weight: 600;'));
            ?>
        </form>
        <div id="contrast-result" style="margin-top: 20px;"></div>
        <div style="margin-top: 20px; font-size: 15px; line-height: 1.2em;">
            <h2 style="font-size: 15px; line-height: 1.2em;">What is AA?</h2>
            <p style="font-size: 15px; line-height: 1.2em;">AA compliance refers to the Web Content Accessibility Guidelines (WCAG) 2.1, which require a contrast ratio of at least 4.5:1 for normal text (minimum 16px) and 3:1 for large text (minimum 24px or 19px bold). This ensures that content is readable and accessible for individuals with moderate visual impairments.</p>
            <h2 style="font-size: 15px; line-height: 1.2em;">What is AAA?</h2>
            <p style="font-size: 15px; line-height: 1.2em;">AAA compliance is the highest level of conformance in WCAG 2.1. It requires a contrast ratio of at least 7:1 for normal text (minimum 16px) and 4.5:1 for large text (minimum 24px or 19px bold). Achieving AAA compliance ensures that content is accessible to the widest range of users, including those with significant visual impairments.</p>
        </div>
    </div>
    <style>
        .my-color-field {
            font-size: 15px !important;
        }
        .contrast-pass-yes {
            color: #007E33; font-weight: 600;
        }
        .contrast-pass-no {
            color: #E60000; font-weight: 600;
        }
    </style>
    <?php
}

// Enqueue the color picker script and add inline script
add_action('admin_enqueue_scripts', 'contrast_checker_enqueue_scripts');
function contrast_checker_enqueue_scripts($hook_suffix) {
    if ($hook_suffix != 'settings_page_contrast-checker') {
        return;
    }
    wp_enqueue_style('wp-color-picker');
    wp_enqueue_script('wp-color-picker');
    wp_add_inline_script('wp-color-picker', '
        jQuery(document).ready(function($) {
            function updateContrast() {
                var bgColor = $("#background_color").val();
                var txtColor = $("#text_color").val();

                $.ajax({
                    url: ajaxurl,
                    type: "POST",
                    data: {
                        action: "check_contrast",
                        bg_color: bgColor,
                        txt_color: txtColor
                    },
                    success: function(response) {
                        if (response.success) {
                            $("#contrast-result").html(response.data);
                        }
                    }
                });
            }

            $(".my-color-field").wpColorPicker({
                defaultColor: {
                    background_color: "#FFFFFF",
                    text_color: "#000000"
                },
                change: function(event, ui) {
                    var color = ui.color.toString();
                    if (event.target.id === "background_color") {
                        $("#background_color_hex").text(color);
                    } else if (event.target.id === "text_color") {
                        $("#text_color_hex").text(color);
                    }
                    updateContrast();
                }
            });

            // Initial contrast check
            updateContrast();
        });
    ');
}

// AJAX handler for checking contrast
add_action('wp_ajax_check_contrast', 'ajax_check_contrast');
function ajax_check_contrast() {
    $bg_color = sanitize_hex_color($_POST['bg_color']);
    $txt_color = sanitize_hex_color($_POST['txt_color']);
    $result = check_contrast($bg_color, $txt_color);
    wp_send_json_success($result);
}

function check_contrast($bg_hex, $txt_hex) {
    $bg_rgb = hex_to_rgb($bg_hex);
    $txt_rgb = hex_to_rgb($txt_hex);

    $bg_luminance = luminance($bg_rgb);
    $txt_luminance = luminance($txt_rgb);

    $contrast_ratio = contrast_ratio($bg_luminance, $txt_luminance);
    $aa_pass = ($contrast_ratio >= 4.5) ? '<span class="contrast-pass-yes">Yes</span>' : '<span class="contrast-pass-no">No</span>';
    $aaa_pass = ($contrast_ratio >= 7) ? '<span class="contrast-pass-yes">Yes</span>' : '<span class="contrast-pass-no">No</span>';

    $suggested_aa = adjust_foreground_color($bg_rgb, $txt_rgb, 4.5);
    $suggested_aaa = adjust_foreground_color($bg_rgb, $txt_rgb, 7);

    return '
        <div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;">
            <div style="background-color: ' . esc_attr($bg_hex) . '; width: 20px; height: 20px; border: 1px solid #000;"></div>
            <div style="background-color: ' . esc_attr($txt_hex) . '; width: 20px; height: 20px; border: 1px solid #000;"></div>
        </div>
        <div style="font-size: 15px; line-height: 1.2em;">
            <div style="margin-bottom: 5px;"><strong>Contrast Ratio:</strong> ' . round($contrast_ratio, 2) . '</div>
            <div style="margin-bottom: 5px;"><strong>AA Compliant:</strong> ' . $aa_pass . '</div>
            <div style="margin-bottom: 5px;"><strong>AAA Compliant:</strong> ' . $aaa_pass . '</div>
        </div>
        <div style="margin-top: 20px; font-size: 15px; line-height: 1.2em;">
            <div style="margin-bottom: 20px;">
                <strong>Suggested Foreground Color for AA:</strong>
                <span style="background-color: ' . $suggested_aa . '; width: 20px; height: 20px; display: inline-block; border: 1px solid #000;"></span> ' . $suggested_aa . '
            </div>
            <div>
                <strong>Suggested Foreground Color for AAA:</strong>
                <span style="background-color: ' . $suggested_aaa . '; width: 20px; height: 20px; display: inline-block; border: 1px solid #000;"></span> ' . $suggested_aaa . '
            </div>
        </div>';
}

function hex_to_rgb($hex) {
    $hex = ltrim($hex, '#');
    $r = hexdec(substr($hex, 0, 2)) / 255;
    $g = hexdec(substr($hex, 2, 2)) / 255;
    $b = hexdec(substr($hex, 4, 2)) / 255;
    return array($r, $g, $b);
}

function rgb_to_hex($rgb) {
    return sprintf("#%02x%02x%02x", round($rgb[0] * 255), round($rgb[1] * 255), round($rgb[2] * 255));
}

function luminance($rgb) {
    list($r, $g, $b) = $rgb;
    $r = ($r <= 0.03928) ? $r / 12.92 : pow(($r + 0.055) / 1.055, 2.4);
    $g = ($g <= 0.03928) ? $g / 12.92 : pow(($g + 0.055) / 1.055, 2.4);
    $b = ($b <= 0.03928) ? $b / 12.92 : pow(($b + 0.055) / 1.055, 2.4);
    return 0.2126 * $r + 0.7152 * $g + 0.0722 * $b;
}

function contrast_ratio($l1, $l2) {
    $lighter = max($l1, $l2);
    $darker = min($l1, $l2);
    return ($lighter + 0.05) / ($darker + 0.05);
}

function adjust_foreground_color($bg_rgb, $txt_rgb, $target_ratio) {
    $bg_luminance = luminance($bg_rgb);
    $step = 0.02; // Adjust step value for precision and performance

    // Incrementally adjust the RGB values to find a compliant color
    for ($i = 0; $i <= 1; $i += $step) {
        $test_rgb = adjust_rgb_lightness($txt_rgb, $i);
        $test_luminance = luminance($test_rgb);
        if (contrast_ratio($test_luminance, $bg_luminance) >= $target_ratio) {
            return rgb_to_hex($test_rgb);
        }

        $test_rgb = adjust_rgb_lightness($txt_rgb, -$i);
        $test_luminance = luminance($test_rgb);
        if (contrast_ratio($test_luminance, $bg_luminance) >= $target_ratio) {
            return rgb_to_hex($test_rgb);
        }
    }

    return "#000000"; // fallback to black if no suitable color found
}

function adjust_rgb_lightness($rgb, $adjustment) {
    return array(
        min(1, max(0, $rgb[0] + $adjustment)),
        min(1, max(0, $rgb[1] + $adjustment)),
        min(1, max(0, $rgb[2] + $adjustment))
    );
}

				
			
				
					// Disable user registration
add_filter('pre_option_users_can_register', '__return_zero');

				
			
				
					/**
 * Duplicate WordPress Posts, Pages, and Custom Post Types as Drafts
 *
 * This code snippet enables the duplication of WordPress posts, pages, and all registered custom post types (CPTs).
 * It adds a 'Duplicate' link to the row actions for each item in the admin dashboard. When clicked, this link
 * triggers the duplication of the selected item, creating a new draft with the same content, custom fields,
 * and taxonomies.
 *
 * Functions:
 * 1. `duplicate_post_as_draft`: Handles the duplication process. It copies the post data, including title,
 *    content, excerpt, and custom fields, and creates a new post with a 'draft' status. It also maintains
 *    the taxonomy terms (like categories and tags) from the original post.
 * 2. `duplicate_post_link`: Adds the 'Duplicate' action link to the WordPress admin interface for each post,
 *    page, and custom post type. This link uses WordPress's built-in nonce functionality for security.
 * 3. `apply_duplicate_post_link_to_cpts`: Dynamically applies the duplicate post link function to all public
 *    post types, ensuring the 'Duplicate' link appears for any custom post types registered on the site.
 *
 * Author: Mark Harris
 * URI: https://www.christchurchwebsolutions.co.uk
 */

function duplicate_post_as_draft() {
    global $wpdb;

    // Verify the nonce for security
    $nonce_action = 'duplicate_post_as_draft';
    $nonce_name = 'duplicate_nonce';
    if (!isset($_GET[$nonce_name]) || !wp_verify_nonce($_GET[$nonce_name], $nonce_action)) {
        wp_die(esc_html__('Security check failed.', 'wpturbo'));
    }

    // Check if the 'post' parameter is set in either GET or POST request
    $post_id = filter_input(INPUT_GET, 'post', FILTER_SANITIZE_NUMBER_INT) ?: filter_input(INPUT_POST, 'post', FILTER_SANITIZE_NUMBER_INT);

    if (!$post_id) {
        wp_die(esc_html__('No post to duplicate has been supplied!', 'wpturbo'));
    }

    // Check if the post exists
    $post = get_post($post_id);
    if (!$post) {
        wp_die(esc_html(sprintf(__('Post creation failed, could not find original post: %s', 'wpturbo'), $post_id)));
    }

    $current_user = wp_get_current_user();
    $new_post_author = $current_user->ID;

    $args = [
        "comment_status" => $post->comment_status,
        "ping_status" => $post->ping_status,
        "post_author" => $new_post_author,
        "post_content" => $post->post_content,
        "post_excerpt" => $post->post_excerpt,
        "post_name" => $post->post_name,
        "post_parent" => $post->post_parent,
        "post_password" => $post->post_password,
        "post_status" => "draft",
        "post_title" => $post->post_title . " (Copy)",
        "post_type" => $post->post_type,
        "to_ping" => $post->to_ping,
        "menu_order" => $post->menu_order
    ];

    $new_post_id = wp_insert_post($args);

    $taxonomies = get_object_taxonomies($post->post_type);
    foreach ($taxonomies as $taxonomy) {
        $post_terms = wp_get_object_terms($post_id, $taxonomy, ["fields" => "slugs"]);
        wp_set_object_terms($new_post_id, $post_terms, $taxonomy, false);
    }

    $post_meta_infos = $wpdb->get_results(
        $wpdb->prepare("SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id = %d", $post_id)
    );
    if (count($post_meta_infos) != 0) {
        foreach ($post_meta_infos as $meta_info) {
            $meta_key = $meta_info->meta_key;
            $meta_value = sanitize_meta($meta_info->meta_key, $meta_info->meta_value, "post");
            $wpdb->insert($wpdb->postmeta, [
                "post_id" => $new_post_id,
                "meta_key" => $meta_key,
                "meta_value" => $meta_value
            ]);
        }
    }

    // Redirect to the post list screen and show a success message
    $redirect_url = admin_url("edit.php?post_type=" . $post->post_type);
    wp_redirect(add_query_arg("message", "101", $redirect_url));
    exit();
}

add_action("admin_action_duplicate_post_as_draft", "duplicate_post_as_draft");

function duplicate_post_link($actions, $post) {
    if (current_user_can('edit_posts')) {
        $actions['duplicate'] = '<a href="' . 
            wp_nonce_url(
                admin_url("admin.php?action=duplicate_post_as_draft&post=" . $post->ID), 
                'duplicate_post_as_draft', 
                'duplicate_nonce'
            ) . 
            '" title="' . esc_attr__('Duplicate this item', 'wpturbo') . 
            '" rel="permalink">' . esc_html__('Duplicate', 'wpturbo') . '</a>';
    }
    return $actions;
}

add_filter("post_row_actions", "duplicate_post_link", 10, 2);
add_filter("page_row_actions", "duplicate_post_link", 10, 2);

function apply_duplicate_post_link_to_cpts() {
    $post_types = get_post_types(["public" => true], "names");
    foreach ($post_types as $post_type) {
        add_filter("{$post_type}_row_actions", "duplicate_post_link", 10, 2);
    }
}

add_action("admin_init", "apply_duplicate_post_link_to_cpts");

function show_duplicate_admin_notice() {
    if (isset($_GET['message']) && $_GET['message'] === '101') {
        echo '<div class="notice notice-success is-dismissible"><p>' . esc_html('Post duplicated successfully.') . '</p></div>';
    }
}

add_action('admin_notices', 'show_duplicate_admin_notice');
				
			
				
					// Function to add the calculator to the admin menu
function ft_calculator_admin_menu()
{
    add_menu_page(
        "Fluid Typography Calculator", // Page title
        "Clamp Calculator", // Menu title
        "manage_options", // Capability
        "fluid-typography-calculator", // Menu slug
        "ft_calculator_page" // Function that displays the page content
    );
}

add_action("admin_menu", "ft_calculator_admin_menu");

// Function that generates the calculator page
function ft_calculator_page() {
    // Initialize the $useRem variable at the start of the function
    $useRem = false;

    echo '<div class="wrap"><h1>Fluid Typography Calculator</h1>';

    // Basic styles for the form and output
    echo '<style>
            .ft-form input[type="number"] {
                width: 100px;
                padding: 8px;
                margin: 4px 0;
                box-sizing: border-box;
                border: 1px solid #ccc;
                border-radius: 4px;
            }
            .ft-form label {
                font-weight: bold;
            }
            .ft-form div {
                margin-bottom: 10px;
            }
			.ft-form textarea {
				width: 100%;  // Adjust this to your preference
				height: 150px; // Or any height that suits your layout
				padding: 8px;
				border: 1px solid #ccc;
				border-radius: 4px;
				margin-top: 10px;
			}
			
			#cssOutput, #cssVariablesOutput {
				width: 50%; // Makes the textarea take up the full width of its container
				max-width: 50%; // You can adjust this as needed
				min-width: 300px; // Ensures a minimum width
				padding: 8px;
				border: 1px solid #ccc;
				border-radius: 4px;
				margin-top: 10px;
			}

            .ft-form button {
                background-color: #4CAF50;
                color: white;
                padding: 10px 15px;
                border: none;
                border-radius: 4px;
                cursor: pointer;
            }
            .ft-form button:hover {
                background-color: #45a049;
            }
            .grid-container {
                display: grid;
                grid-template-columns: repeat(5, 1fr);
                gap: 10px;
            }
          </style>';

// Initialize variables
    $rootFontSize = isset($_POST["rootFontSize"]) ? $_POST["rootFontSize"] : 16;
    $defaultValues = [
        "h1" => [
            "MinWidth" => 380,
            "MinFontSize" => 29,
            "MaxWidth" => 1600,
            "MaxFontSize" => 68,
        ],
        "h2" => [
            "MinWidth" => 380,
            "MinFontSize" => 24,
            "MaxWidth" => 1600,
            "MaxFontSize" => 51,
        ],
        "h3" => [
            "MinWidth" => 380,
            "MinFontSize" => 20,
            "MaxWidth" => 1600,
            "MaxFontSize" => 38,
        ],
        "h4" => [
            "MinWidth" => 380,
            "MinFontSize" => 17,
            "MaxWidth" => 1600,
            "MaxFontSize" => 29,
        ],
        "h5" => [
            "MinWidth" => 380,
            "MinFontSize" => 14,
            "MaxWidth" => 1600,
            "MaxFontSize" => 22,
        ],
        "h6" => [
            "MinWidth" => 380,
            "MinFontSize" => 12,
            "MaxWidth" => 1600,
            "MaxFontSize" => 16,
        ],
        "body" => [
            "MinWidth" => 380,
            "MinFontSize" => 16,
            "MaxWidth" => 1600,
            "MaxFontSize" => 24,
        ],
        "p" => [
            "MinWidth" => 380,
            "MinFontSize" => 16,
            "MaxWidth" => 1600,
            "MaxFontSize" => 24,
        ],
    ];

    $cssOutput = ""; // Initialize traditional CSS output string
    $cssVariablesOutput = ""; // Initialize CSS variables output string

    // Check if form is submitted
    if ($_SERVER["REQUEST_METHOD"] == "POST") {
        $useRem = isset($_POST["unitToggle"]) && $_POST["unitToggle"] === 'on';
        // Security check using nonce
        if (!isset($_POST["ft_calculator_nonce_field"]) || !wp_verify_nonce($_POST["ft_calculator_nonce_field"], "ft_calculator_action")) {
            echo "<p>Security check failed. Please try again.</p>";
            return;
        }

foreach (["h1", "h2", "h3", "h4", "h5", "h6", "body", "p"] as $tag) {
            $minWidth = $_POST[$tag . "MinWidth"]; // In pixels
            $minFontSizePx = $_POST[$tag . "MinFontSize"]; // In pixels or REM based on $useRem
            $maxWidth = $_POST[$tag . "MaxWidth"]; // In pixels
            $maxFontSizePx = $_POST[$tag . "MaxFontSize"]; // In pixels or REM based on $useRem

            // Handle unit conversion
            if ($useRem) {
                // Convert REM to Pixels for internal calculation
                $minFontSizePx *= $rootFontSize;
                $maxFontSizePx *= $rootFontSize;
            }

            // Convert pixel values to REM for CSS generation
            $minFontSize = $minFontSizePx / $rootFontSize; // In rem
            $maxFontSize = $maxFontSizePx / $rootFontSize; // In rem

            // Convert widths from px to vw (assuming 1rem = rootFontSize px)
            $minWidthVW = $minWidth / $rootFontSize; // In vw
            $maxWidthVW = $maxWidth / $rootFontSize; // In vw

            // Calculate the CSS
            $vwUnit =
                (($maxFontSize - $minFontSize) / ($maxWidthVW - $minWidthVW)) *
                100;
            $constant = $minFontSize - ($vwUnit * $minWidthVW) / 100;

            // Format to a maximum of 5 decimal places
            $vwUnitFormatted = number_format($vwUnit, 5, ".", "");
            $constantFormatted = number_format($constant, 5, ".", "");

            // Add to traditional CSS output
            $cssOutput .=
                "{$tag} {font-size: clamp(" .
                $minFontSize .
                "rem, " .
                $constantFormatted .
                "rem + " .
                $vwUnitFormatted .
                "vw, " .
                $maxFontSize .
                "rem);}\n";

            // Add to CSS variables output
            $cssVariablesOutput .=
                "  --{$tag}-font-size: clamp(" .
                $minFontSize .
                "rem, " .
                $constantFormatted .
                "rem + " .
                $vwUnitFormatted .
                "vw, " .
                $maxFontSize .
                "rem);\n";
        }

        // Wrap CSS variables in a :root selector
        $cssVariablesOutput = ":root {\n" . $cssVariablesOutput . "}\n";
    }

// Display the form
echo '<form class="ft-form" method="post">';
wp_nonce_field("ft_calculator_action", "ft_calculator_nonce_field");

echo '<div>
        <label for="rootFontSize">Root HTML Font Size (px):</label>
        <input type="number" id="rootFontSize" name="rootFontSize" required value="' . htmlspecialchars($rootFontSize) . '">
      </div>
      <div>
        <label for="unitToggle">Use REM Units for Font Size:</label>
        <input type="checkbox" id="unitToggle" name="unitToggle" ' . ($useRem ? 'checked' : '') . ' onchange="toggleUnits()">
      </div>';

echo '<div class="grid-container">
        <div><strong>Tag</strong></div>
        <div><strong>Min Width (px)</strong></div>
        <div><strong>Min Font Size (' . ($useRem ? 'rem' : 'px') . ')</strong></div>
        <div><strong>Max Width (px)</strong></div>
        <div><strong>Max Font Size (' . ($useRem ? 'rem' : 'px') . ')</strong></div>';

// Display input fields for each tag
foreach (["h1", "h2", "h3", "h4", "h5", "h6", "body", "p"] as $tag) {
    $minWidthValue = isset($_POST[$tag . "MinWidth"]) ? $_POST[$tag . "MinWidth"] : $defaultValues[$tag]["MinWidth"];
    $minFontSizeValue = isset($_POST[$tag . "MinFontSize"]) ? $_POST[$tag . "MinFontSize"] : $defaultValues[$tag]["MinFontSize"];
    $maxWidthValue = isset($_POST[$tag . "MaxWidth"]) ? $_POST[$tag . "MaxWidth"] : $defaultValues[$tag]["MaxWidth"];
    $maxFontSizeValue = isset($_POST[$tag . "MaxFontSize"]) ? $_POST[$tag . "MaxFontSize"] : $defaultValues[$tag]["MaxFontSize"];

echo "<div><strong>{$tag}</strong></div>
          <div><input type='number' id='{$tag}MinWidth' name='{$tag}MinWidth' class='unit-input' required value='{$minWidthValue}'></div>
          <div><input type='number' id='{$tag}MinFontSize' name='{$tag}MinFontSize' class='unit-input' step='0.01' required value='{$minFontSizeValue}'></div>
          <div><input type='number' id='{$tag}MaxWidth' name='{$tag}MaxWidth' class='unit-input' required value='{$maxWidthValue}'></div>
          <div><input type='number' id='{$tag}MaxFontSize' name='{$tag}MaxFontSize' class='unit-input' step='0.01' required value='{$maxFontSizeValue}'></div>";
}


echo '</div><input type="submit" value="Generate CSS"></form>';


    // Display the traditional CSS output
    if (!empty($cssOutput)) {
        echo "<h2>Generated CSS:</h2>";
        echo '<textarea id="cssOutput" rows="10">' . htmlspecialchars($cssOutput) . "</textarea><br>";
        echo '<button onclick="copyToClipboard(\'cssOutput\')">Copy CSS</button>';
    }

    // Display the CSS variables output
    if (!empty($cssVariablesOutput)) {
        echo "<h2>Generated CSS Variables:</h2>";
        echo '<textarea id="cssVariablesOutput" rows="10">' . htmlspecialchars($cssVariablesOutput) . "</textarea><br>";
        echo '<button onclick="copyToClipboard(\'cssVariablesOutput\')">Copy CSS Variables</button>';
    }

    // JavaScript for copy to clipboard functionality and unit conversion
    echo '<script>
            function copyToClipboard(elementId) {
                var copyText = document.getElementById(elementId);
                copyText.select();
                document.execCommand("copy");
            }

function toggleUnits() {
    var useRem = document.getElementById("unitToggle").checked;
    var rootFontSize = parseFloat(document.getElementById("rootFontSize").value);
    var fontSizeElements = document.querySelectorAll(".unit-input"); // Class for font size inputs

    fontSizeElements.forEach(function(element) {
        if (element.id.endsWith("MinFontSize") || element.id.endsWith("MaxFontSize")) {
            var value = parseFloat(element.value);
            if (!isNaN(value)) {
                if (useRem) {
                    element.value = (value / rootFontSize).toFixed(2); // Convert to REM
                } else {
                    element.value = (value * rootFontSize).toFixed(0); // Convert to Pixels
                }
            }
        }
    });
}

          </script>';

    echo "</div>";
}


// Define the function for the fluid typography calculator
function fluid_typography_calculator() {
    // Call the existing function to display the fluid typography calculator
    ft_calculator_page();
}

// Add the shortcode
add_shortcode('Fluid_calc', 'fluid_typography_calculator');

				
			
				
					add_filter( 'media_library_infinite_scrolling', '__return_true' );
				
			
				
					function custom_mime_types($mimes) {
    $mimes['woff'] = 'font/woff';
    $mimes['woff2'] = 'font/woff2';
    return $mimes;
}
add_filter('upload_mimes', 'custom_mime_types');

				
			
				
					function limit_image_sizes($sizes) {
    // Keep only the thumbnail size
    return array(
        'thumbnail' => $sizes['thumbnail']
    );
}
add_filter('intermediate_image_sizes_advanced', 'limit_image_sizes');

function set_thumbnail_size() {
    // Set the thumbnail size to 150x150
    update_option('thumbnail_size_w', 150);
    update_option('thumbnail_size_h', 150);
    update_option('thumbnail_crop', 1); // 1 for hard crop, 0 for soft crop
}
add_action('admin_init', 'set_thumbnail_size');

// Remove the unnecessary regenerate_thumbnails function as the thumbnail is already handled

				
			
				
					function restrict_plugins_page() {
    // Check if the current user is trying to access the Plugins page
    global $pagenow;
    if ($pagenow === 'plugins.php' || strpos($_SERVER['REQUEST_URI'], 'plugin-install.php') !== false || strpos($_SERVER['REQUEST_URI'], 'plugin-editor.php') !== false) {
        
        // Start a session if not already started
        if (!session_id()) {
            session_start();
        }
        
        // SET THE PASSWORD HERE !!
        $required_password = '123'; // Change this to your desired password
        
        // Check if the password has been submitted and is correct
        if (isset($_POST['plugins_password']) && $_POST['plugins_password'] === $required_password) {
            $_SESSION['plugins_access_granted'] = true;
        }
        
        // Check if the session variable is not set, meaning access is not granted
        if (empty($_SESSION['plugins_access_granted'])) {
            // Display the password form
            echo '<form method="post" action="">
                <p>Enter the password to access the Plugins page:</p>
                <input type="password" name="plugins_password" />
                <input type="submit" value="Submit" />
            </form>';
            
            // Prevent the rest of the Plugins page from loading
            exit;
        }
    }
}
add_action('admin_init', 'restrict_plugins_page');

				
			
				
					function restrict_settings_page() {
    // Check if the current user is trying to access the Settings page
    global $pagenow;
    $settings_pages = array(
        'options-general.php',
        'options-writing.php',
        'options-reading.php',
        'options-discussion.php',
        'options-media.php',
        'options-permalink.php',
        // Add more settings pages if you have plugins that add their own settings
    );

    if (in_array($pagenow, $settings_pages)) {
        
        // Start a session if not already started
        if (!session_id()) {
            session_start();
        }
        
        // Set the password
        $required_password = '123'; // Change this to your desired password
        
        // Check if the password has been submitted and is correct
        if (isset($_POST['settings_password']) && $_POST['settings_password'] === $required_password) {
            $_SESSION['settings_access_granted'] = true;
        }
        
        // Check if the session variable is not set, meaning access is not granted
        if (empty($_SESSION['settings_access_granted'])) {
            // Display the password form
            echo '<form method="post" action="">
                <p>Enter the password to access the Settings page:</p>
                <input type="password" name="settings_password" />
                <input type="submit" value="Submit" />
            </form>';
            
            // Prevent the rest of the Settings page from loading
            exit;
        }
    }
}
add_action('admin_init', 'restrict_settings_page');

				
			
				
					if (!function_exists('restrict_snippets_pages')) {
    function restrict_snippets_pages() {
        // Check if the current user is trying to access the Snippets pages
        global $pagenow;
        $restricted_pages = array(
            'admin.php?page=snippets',
            'admin.php?page=snippet-manager',
            'admin.php?page=snippet-import',
            'admin.php?page=add-snippet',
            'admin.php?page=import-code-snippets'
        );

        // Check if the current request URI contains any of the restricted pages
        $is_restricted_page = false;
        foreach ($restricted_pages as $restricted_page) {
            if (strpos($_SERVER['REQUEST_URI'], $restricted_page) !== false) {
                $is_restricted_page = true;
                break;
            }
        }

        if ($is_restricted_page) {
            // Start a session if not already started
            if (!session_id()) {
                session_start();
            }
            
            // SET THE PASSWORD HERE !!
            $required_password = '123'; // Change this to your desired password
            
            // Check if the password has been submitted and is correct
            if (isset($_POST['snippets_password']) && $_POST['snippets_password'] === $required_password) {
                $_SESSION['snippets_access_granted'] = true;
            }
            
            // Check if the session variable is not set, meaning access is not granted
            if (empty($_SESSION['snippets_access_granted'])) {
                // Display the password form
                echo '<form method="post" action="">
                    <p>Enter the password to access the Snippets pages:</p>
                    <input type="password" name="snippets_password" />
                    <input type="submit" value="Submit" />
                </form>';
                
                // Prevent the rest of the Snippets page from loading
                exit;
            }
        }
    }
    add_action('admin_init', 'restrict_snippets_pages');
}

				
			
				
					function restrict_users_page() {
    // Check if the current user is trying to access the Users page
    global $pagenow;
    if ($pagenow === 'users.php' || $pagenow === 'user-new.php' || $pagenow === 'profile.php') {
        
        // Start a session if not already started
        if (!session_id()) {
            session_start();
        }
        
        // Set the password
        $required_password = '123'; // Change this to your desired password
        
        // Check if the password has been submitted and is correct
        if (isset($_POST['users_password']) && $_POST['users_password'] === $required_password) {
            $_SESSION['users_access_granted'] = true;
        }
        
        // Check if the session variable is not set, meaning access is not granted
        if (empty($_SESSION['users_access_granted'])) {
            // Display the password form
            echo '<form method="post" action="">
                <p>Enter the password to access the Users page:</p>
                <input type="password" name="users_password" />
                <input type="submit" value="Submit" />
            </form>';
            
            // Prevent the rest of the Users page from loading
            exit;
        }
    }
}
add_action('admin_init', 'restrict_users_page');

				
			
				
					if ( ! function_exists( 'custom_set_permalink_structure_to_post_name' ) ) {
    /**
     * Sets the default permalink structure to 'Post Name' if it is not already set.
     *
     * To change the default permalink structure, update the `$desired_permalink_structure`
     * variable with one of the following values:
     *
     * - Plain: ''
     * - Day and Name: '/%year%/%monthnum%/%day%/%postname%/'
     * - Month and Name: '/%year%/%monthnum%/%postname%/'
     * - Numeric: '/%post_id%/'
     * - Post Name: '/%postname%/'
     * - Custom Structure: '/your/custom/structure/'
     */
    function custom_set_permalink_structure_to_post_name() {
        // Get the current permalink structure
        $current_permalink_structure = get_option('permalink_structure');

        // Set the desired permalink structure here
        // Default is 'Post Name'
        $desired_permalink_structure = '/%postname%/';

        // Uncomment one of the following lines to set a different permalink structure
        // Plain: 
        // $desired_permalink_structure = '';
        
        // Day and Name: 
        // $desired_permalink_structure = '/%year%/%monthnum%/%day%/%postname%/';
        
        // Month and Name: 
        // $desired_permalink_structure = '/%year%/%monthnum%/%postname%/';
        
        // Numeric: 
        // $desired_permalink_structure = '/%post_id%/';
        
        // Custom Structure: 
        // $desired_permalink_structure = '/your/custom/structure/';

        // Check if the current structure is not already set to the desired structure
        if ($current_permalink_structure != $desired_permalink_structure) {
            // Update the permalink structure
            update_option('permalink_structure', $desired_permalink_structure);
            // Flush rewrite rules to apply the new permalink structure
            flush_rewrite_rules();
        }
    }
    add_action('admin_init', 'custom_set_permalink_structure_to_post_name');
}

				
			
				
					/*
Plugin Name: Purge Cache
Description: Adds a button to the WordPress dashboard to clear the object cache
*/

add_action( 'admin_bar_menu', 'add_purge_cache_button', 999 );

function add_purge_cache_button( $wp_admin_bar ) {
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }

    $args = array(
        'id'    => 'purge-cache',
        'title' => 'Purge Cache',
        'href'  => '#',
        'meta'  => array( 'class' => 'purge-cache' )
    );
    $wp_admin_bar->add_node( $args );
}

add_action( 'admin_footer', 'add_purge_cache_script' );

function add_purge_cache_script() {
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }
    ?>
    <script>
    jQuery(document).ready(function($) {
        $('#wp-admin-bar-purge-cache').click(function() {
            if (confirm('Are you sure you want to purge the cache?')) {
                $.ajax({
                    url: '<?php echo admin_url( 'admin-ajax.php' ); ?>',
                    data: {
                        action: 'purge_cache',
                    },
                    success: function() {
                        alert('Cache purged successfully!');
                    },
                    error: function() {
                        alert('An error occurred while purging the cache.');
                    }
                });
            }
        });
    });
    </script>
    <?php
}

add_action( 'wp_ajax_purge_cache', 'purge_cache_callback' );

function purge_cache_callback() {
    global $wp_object_cache;
    if ( ! current_user_can( 'manage_options' ) ) {
        wp_die();
    }

    wp_cache_flush();

    wp_die();
}
				
			
				
					/*
Comments in WordPress are like an open mic.
Sometimes you want to turn the mic off.
Silencing the comment section might just be your ticket to serenity.*/

function codesnippets_disable_comments() {
    // Remove comment support for posts
    remove_post_type_support( 'post', 'comments' );

    // Remove comment support for pages
    remove_post_type_support( 'page', 'comments' );

    // Remove comments from the admin menu
    remove_menu_page( 'edit-comments.php' );

    // Redirect comment-related URLs to the homepage
    add_action( 'template_redirect', 'codesnippets_disable_comments_redirect' );
}

function codesnippets_disable_comments_redirect() {
    global $wp_query;
    if ( is_single() || is_page() || is_attachment() ) {
        if ( have_comments() || comments_open() ) {
            wp_redirect( home_url(), 301 );
            exit;
        }
    }
}

add_action( 'admin_init', 'codesnippets_disable_comments' );
				
			
				
					function remove_dashboard_widgets() {
    remove_action( 'welcome_panel', 'wp_welcome_panel' );
    remove_meta_box( 'dashboard_right_now', 'dashboard', 'normal' );
    remove_meta_box( 'dashboard_activity', 'dashboard', 'normal' );
    remove_meta_box( 'dashboard_quick_press', 'dashboard', 'side' );
    remove_meta_box( 'dashboard_primary', 'dashboard', 'side' );
    remove_meta_box( 'dashboard_site_health', 'dashboard', 'normal' );
	 remove_meta_box( 'e-dashboard-overview', 'dashboard', 'normal' );
}
add_action( 'wp_dashboard_setup', 'remove_dashboard_widgets' );
				
			
				
					add_action('save_post', function ($post_id, $post, $update) {
    // Check if the post is an instance of Elementor's Kit
    if ('elementor_library' === get_post_type($post_id) && 'kit' === get_post_meta($post_id, '_elementor_template_type', true)) {
        $meta = get_post_meta($post_id, '_elementor_page_settings', true);

        // Handle custom colors
        if (!empty($meta['custom_colors'])) {
            foreach ($meta['custom_colors'] as &$custom_color) {
                // Replace the hyphens inside of titles with underscores to ensure consistency
                $custom_color['_id'] = str_replace('-', '_', sanitize_title($custom_color['title']));
            }
        }

        // Update post meta
        update_post_meta($post_id, '_elementor_page_settings', $meta);
    }
}, 10, 3);

				
			
				
					define('WP_POST_REVISIONS', 3);
				
			

This comes in 3 parts.

  1. HTML Widget for the Toggle, adjust the CSS for styling. Place in your Header Template or anywhere else on your site.
  2. Add the Code Snippet to Code Snippets.
  3. Use the CSS as an example of how to style for the Light and Dark Mode. Note that using the Custom Global Colours CSS will help with using Custom Colours. The CSS should be added to Site Settings or any Customised CSS area.

Part 1: The HTML

				
					<div class="mode-toggle">
  <input type="checkbox" id="mode-switch" aria-label="Toggle dark mode" role="switch" aria-checked="false" />
  <label for="mode-switch" class="toggle-label">
    <span class="light-mode">
      <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
        <circle cx="12" cy="12" r="5"></circle>
        <line x1="12" y1="1" x2="12" y2="3"></line>
        <line x1="12" y1="21" x2="12" y2="23"></line>
        <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
        <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
        <line x1="1" y1="12" x2="3" y2="12"></line>
        <line x1="21" y1="12" x2="23" y2="12"></line>
        <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
        <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
      </svg>
    </span>
    <span class="dark-mode">
      <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
        <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
      </svg>
    </span>
  </label>
</div>


<style>
/* Toggle switch container */
.mode-toggle {
  position: relative;
  display: inline-block;
  width: 55px;
  height: 28px;
}

/* Hide default checkbox */
.mode-toggle input {
  opacity: 0;
  width: 0;
  height: 0;
}

/* Custom slider */
.toggle-label {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: #000;
  border-radius: 28px;
  cursor: pointer;
  transition: background-color 0.2s;
}

/* Slider before/after */
.toggle-label::before {
  position: absolute;
  content: "";
  height: 20px;
  width: 20px;
  left: 4px;
  bottom: 4px;
  background-color: #fff;
  border-radius: 50%;
  transition: transform 0.3s, background-color 0.3s;
  z-index: 999;
}

/* Light and Dark labels */
.light-mode,
.dark-mode {
  position: absolute;
  width: 50%;
  height: 100%;
  text-align: center;
  line-height: 28px;
  font-size: 12px;
  font-weight: bold;
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: color 0.3s;
}

.light-mode {
  left: 0;
}

.dark-mode {
  right: 0;
}

/* When checked, move the slider */
input:checked + .toggle-label {
  background-color: #fff;
}

input:checked + .toggle-label::before {
  transform: translateX(26px);
  background-color: #000;
}

/* Change label colors when in dark mode */
input:checked + .toggle-label .light-mode,
input:checked + .toggle-label .dark-mode {
  color: #000;
}

/* Smooth transition for body and headings */
body {
  transition: background-color 0.3s ease-in-out, color 0.3s ease-in-out;
}

body h1, body h2, body h3, body h4, body h5, body h6 {
  transition: color 0.2s ease-in-out;
}
</style>
				
			

Part 2: The Snippet

				
					add_action('wp_head', 'dark_mode_toggle_script');

function dark_mode_toggle_script() {
  ?>
  <script>
  document.addEventListener('DOMContentLoaded', (event) => {
    const modeSwitch = document.querySelector('#mode-switch');
    const isDarkMode = localStorage.getItem('darkMode') === 'true';

    // Function to update the mode
    const setMode = (dark) => {
      document.body.classList.toggle('darkMode', dark);
      modeSwitch.setAttribute('aria-checked', dark);
      localStorage.setItem('darkMode', dark);
    };

    // Set initial mode based on localStorage
    setMode(isDarkMode);

    // Toggle mode on button click
    modeSwitch.addEventListener('change', () => {
      const darkModeEnabled = modeSwitch.checked;
      setMode(darkModeEnabled);
    });

    // Keyboard accessibility: toggle dark mode on Enter and Spacebar key press
    modeSwitch.addEventListener('keypress', (event) => {
      if (event.key === 'Enter' || event.key === ' ') {
        modeSwitch.checked = !modeSwitch.checked;
        modeSwitch.dispatchEvent(new Event('change'));
        event.preventDefault();
      }
    });
  });
  </script>
  <?php
}

				
			

Part 3: Example CSS

				
					html { font-size: 100%; } /* Default is always 16px */

/* Text */
h1 {
  font-size: clamp(2.5rem, 1.75rem + 3vw, 4rem);
  font-weight: 900;
  color: var(--e-global-color-primary);
}

.darkMode h1 {
  color: #FFF;
}

h2 {
  font-size: 2rem;
  font-weight: 600;
  color: var(--e-global-color-secondary);
}

.darkMode h2 {
  color: #D0D0CE;
}

.purple h2 {
  font-size: 1.5rem;
  font-weight: 900;
  color: var(--e-global-color-purple_shade);
}

.darkMode .purple h2 {
  color: var(--e-global-color-dark_mode_yellow);
}

p {
  font-size: clamp(1rem, 0.875rem + 0.5vw, 1.25rem);
  font-weight: normal;
  color: var(--e-global-color-text);
}

.darkMode p {
  color: var(--e-global-color-white);
}

/* Backgrounds */
body {
  background-color: #FFF; /* Light background */
}

.darkMode {
  background-color: #000; /* Dark background */
}

.hero_banner {
  background-color: #EFEFEF;
}

.darkMode .hero_banner {
  background-color: #222222;
}

/* Buttons */
.elementor-button {
  background-color: var(--e-global-color-primary);
  color: #FFF;
}

.elementor-button:hover {
  background-color: #000;
}

.darkMode .elementor-button {
  background-color: #F3F3F3;
  color: #000;
}

.darkMode .purple_shade .elementor-button {
  background-color: var(--e-global-color-dark_mode_yellow);
  color: #000;
}

/* Applied to Menu */
.elementor-nav-menu a {
  color: #000;
}

.darkMode .elementor-nav-menu a {
  color: var(--e-global-color-dark_mode_yellow);
}

/* Images */
.darkMode img {
  filter: brightness(0.7) contrast(1.1);
}

.darkMode .grayscale img {
  filter: grayscale(1); /* Between 0 and 1 */
}

.darkMode .saturate img {
  filter: saturate(1.5); /* 1+ increase, <1 decrease */
}

.darkMode .sepia img {
  filter: sepia(1); /* Between 0 and 1 */
}

/* SVG Icons */
.elementor-icon svg {
  fill: #000;
}

.darkMode .elementor-icon svg {
  fill: var(--e-global-color-dark_mode_yellow);
}
				
			
				
					add_filter( 'elementor_pro/custom_fonts/font_display', function( $current_value, $font_family, $data ) {
	return 'swap';
}, 10, 3 );
				
			
				
					add_filter( 'elementor/frontend/print_google_fonts', '__return_false' );
				
			
				
					/**
 * We will Dequeue the jQuery UI script as example.
 *
 * Hooked to the wp_print_scripts action, with a late priority (99),
 * so that it is after the script was enqueued.
 */
function wp_remove_scripts() {
// check if user is admin
 if (current_user_can( 'update_core' )) {
            return;
        }
 else {
    // Check for the page you want to target
    if ( is_page( 'homepage' ) ) {
        // Remove Scripts
  wp_dequeue_style( 'jquery-ui-core' );
     }
 }
}
add_action( 'wp_enqueue_scripts', 'wp_remove_scripts', 99 );
				
			
				
					add_filter( 'wp_lazy_loading_enabled', '__return_false' );
				
			

Excellent

Click Download for your file

Welcome