persona section overhaul — editorial gap-px grid + fresh photography
SECTION REDESIGN: - Killed standalone dashboard image (fake AI laptop, added nothing) - New gap-px grid (signature pattern 2) with border-l-2 accents (pattern 1) - Numbered anchors (01-04) as visual rhythm per brand guide - Wider container: max-w-7xl matches hero width PERSONA CHANGES: - Renamed 'Organisation' -> 'Programme Manager' - Reorder: Charity Manager, Programme Manager, Personal Fundraiser, Volunteer - Updated /for/organisations page content to match PHOTOGRAPHY (4 new images via gemini-3-pro-image-preview): - persona-charity-manager.jpg — hijabi woman at mosque office desk - persona-programme-manager.jpg — man at desk with campaign calendar - persona-fundraiser.jpg — woman on London park bench with phone - persona-volunteer.jpg — young man handing card at charity gala - All optimized: 2.7MB -> 342KB (87% reduction via sharp) - Consistent documentary candid style, 3:2 landscape, warm tones FOOTER: - 'Organisations' -> 'Programme Managers' in nav links
84
gen_personas.py
Normal file
@@ -0,0 +1,84 @@
|
||||
"""Generate 4 persona images for the landing page gap-px grid.
|
||||
All landscape 3:2, documentary candid, consistent warm tone.
|
||||
Uses gemini-3-pro-image-preview (Nano Banana Pro).
|
||||
"""
|
||||
import os, time, sys
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
from google import genai
|
||||
from google.genai import types
|
||||
|
||||
client = genai.Client(api_key="AIzaSyCHnesXLjPw-UgeZaQotut66bgjFdvy12E")
|
||||
OUT = "pledge-now-pay-later/public/images/landing"
|
||||
|
||||
PROMPTS = {
|
||||
"persona-charity-manager.jpg": (
|
||||
"A British South Asian woman in her late 40s wearing a navy cardigan and simple hijab, "
|
||||
"sitting at a desk in a mosque community room. She is looking down at a laptop screen, focused, "
|
||||
"one hand on the trackpad. Warm tungsten overhead lights. A prayer timetable is pinned to a "
|
||||
"corkboard on the wall behind her. Stacks of folders and a mug of tea on the desk. "
|
||||
"Shot on Canon EOS R5, 50mm, f/2.0, available light. Documentary candid, not looking at camera. "
|
||||
"Warm, grounded, purposeful. 3:2 landscape aspect ratio."
|
||||
),
|
||||
"persona-programme-manager.jpg": (
|
||||
"A British Arab man in his mid-30s wearing a smart navy polo shirt, sitting alone at a desk "
|
||||
"in a modern charity office. He has a laptop open and a printed spreadsheet with highlighted rows "
|
||||
"beside it. He is writing notes in a Moleskine notebook, pen in hand, concentrating. "
|
||||
"Natural window light from the left, soft shadows. A monitor showing a campaign calendar is "
|
||||
"blurred in the background. Clean desk, professional but not corporate. "
|
||||
"Shot on Canon EOS R5, 35mm, f/1.8, available light. Documentary candid. "
|
||||
"Organised, calm authority. 3:2 landscape aspect ratio."
|
||||
),
|
||||
"persona-fundraiser.jpg": (
|
||||
"A young British Black woman in her mid-20s sitting on a bench in a London park, looking at her "
|
||||
"phone screen. She wears a casual olive utility jacket and has a tote bag beside her. "
|
||||
"Overcast British daylight, soft diffused light. Shallow depth of field — bare winter trees and "
|
||||
"a path blurred behind her. She looks focused and slightly pleased at something on the screen. "
|
||||
"Shot on Sony A7III, 85mm, f/1.4, natural light. Documentary street photography. "
|
||||
"Independent, resourceful. 3:2 landscape aspect ratio."
|
||||
),
|
||||
"persona-volunteer.jpg": (
|
||||
"A young British South Asian man in his early 20s wearing a lanyard and a plain dark polo shirt, "
|
||||
"leaning forward at a round table during a charity dinner gala. He is handing a small card "
|
||||
"to a seated older woman across the table. Warm gala tungsten lighting, white tablecloths, "
|
||||
"bokeh chandeliers in the background. Other guests are blurred but visible at adjacent tables. "
|
||||
"Shot on Canon EOS R5, 50mm, f/1.8, available light. Documentary candid event photography. "
|
||||
"Energetic, helpful. 3:2 landscape aspect ratio."
|
||||
),
|
||||
}
|
||||
|
||||
def generate(filename, prompt):
|
||||
t0 = time.time()
|
||||
print(f" [GEN] {filename}...")
|
||||
try:
|
||||
resp = client.models.generate_content(
|
||||
model="gemini-3-pro-image-preview",
|
||||
contents=prompt,
|
||||
config=types.GenerateContentConfig(
|
||||
response_modalities=["TEXT", "IMAGE"],
|
||||
),
|
||||
)
|
||||
for part in resp.candidates[0].content.parts:
|
||||
if part.inline_data:
|
||||
path = os.path.join(OUT, filename)
|
||||
with open(path, "wb") as f:
|
||||
f.write(part.inline_data.data)
|
||||
sz = os.path.getsize(path) / 1024
|
||||
print(f" [OK] {filename} -- {sz:.0f}KB ({time.time()-t0:.1f}s)")
|
||||
return filename, True
|
||||
print(f" [FAIL] {filename} -- no image in response")
|
||||
return filename, False
|
||||
except Exception as e:
|
||||
print(f" [FAIL] {filename} -- {e}")
|
||||
return filename, False
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"Generating {len(PROMPTS)} persona images...")
|
||||
ok, fail = 0, 0
|
||||
# Generate 2 at a time (rate limits)
|
||||
with ThreadPoolExecutor(max_workers=2) as pool:
|
||||
futures = {pool.submit(generate, fn, p): fn for fn, p in PROMPTS.items()}
|
||||
for f in as_completed(futures):
|
||||
_, success = f.result()
|
||||
if success: ok += 1
|
||||
else: fail += 1
|
||||
print(f"\nDone: {ok} ok, {fail} failed")
|
||||
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 77 KiB |
BIN
pledge-now-pay-later/public/images/landing/persona-volunteer.jpg
Normal file
|
After Width: | Height: | Size: 88 KiB |
@@ -27,7 +27,7 @@ export function Footer({ active }: { active?: string }) {
|
||||
{ href: "/for/charities", label: "Charities" },
|
||||
{ href: "/for/fundraisers", label: "Fundraisers" },
|
||||
{ href: "/for/volunteers", label: "Volunteers" },
|
||||
{ href: "/for/organisations", label: "Organisations" },
|
||||
{ href: "/for/organisations", label: "Programme Managers" },
|
||||
]
|
||||
return (
|
||||
<footer className="py-10 px-6 border-t border-gray-100">
|
||||
|
||||
@@ -10,12 +10,12 @@ export default function ForOrganisationsPage() {
|
||||
<section className="pt-24 pb-16 md:pt-32 md:pb-20 px-6">
|
||||
<div className="max-w-5xl mx-auto grid md:grid-cols-2 gap-12 items-center">
|
||||
<div className="space-y-6">
|
||||
<p className="text-sm font-semibold text-success-green tracking-wide uppercase">For organisations</p>
|
||||
<p className="text-sm font-semibold text-success-green tracking-wide uppercase">For programme managers</p>
|
||||
<h1 className="text-4xl md:text-5xl font-black text-gray-900 leading-[1.08] tracking-tight">
|
||||
10 charities pledged to your project. Who's actually paid?
|
||||
5 campaigns running. 20 volunteers active. Who's actually collecting?
|
||||
</h1>
|
||||
<p className="text-lg text-gray-500 leading-relaxed">
|
||||
Coordinating a multi-org project, umbrella appeal, or institutional partnership? Track commitments from organisations — not just individuals — and see who's delivered on their promise.
|
||||
Coordinating pledge collection across multiple campaigns, teams, or events? Get the full pipeline view — every pledge, every volunteer, every instalment — in one place.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 pt-2">
|
||||
<Link href="/signup" className="inline-flex items-center justify-center bg-gray-900 px-8 py-4 text-base font-bold text-white hover:bg-gray-800 transition-colors">
|
||||
@@ -33,7 +33,7 @@ export default function ForOrganisationsPage() {
|
||||
{/* ── Use cases ── */}
|
||||
<section className="py-24 bg-gray-50 px-6">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-black text-gray-900 tracking-tight mb-12">When organisations pledge to each other</h2>
|
||||
<h2 className="text-3xl font-black text-gray-900 tracking-tight mb-12">When you're coordinating the bigger picture</h2>
|
||||
<div className="grid md:grid-cols-2 gap-px bg-gray-200">
|
||||
{[
|
||||
{ title: "Multi-charity projects", desc: "Building a school? 5 charities each pledged £100k. Track each commitment, send reminders before due dates, see the full pipeline." },
|
||||
@@ -54,7 +54,7 @@ export default function ForOrganisationsPage() {
|
||||
<section className="py-24 px-6">
|
||||
<div className="max-w-5xl mx-auto grid md:grid-cols-2 gap-16 items-start">
|
||||
<div>
|
||||
<h2 className="text-3xl font-black text-gray-900 tracking-tight mb-12">How it works for organisations</h2>
|
||||
<h2 className="text-3xl font-black text-gray-900 tracking-tight mb-12">How it works for programme managers</h2>
|
||||
<div className="space-y-8">
|
||||
{[
|
||||
{ n: "01", title: "Create a campaign for the project", desc: "\"New School Build 2026\", \"Joint Emergency Appeal\". Set total goal." },
|
||||
@@ -104,8 +104,8 @@ export default function ForOrganisationsPage() {
|
||||
</section>
|
||||
|
||||
<BottomCta
|
||||
headline="Stop chasing partner organisations."
|
||||
sub="Track every commitment. Automate every reminder. Free forever."
|
||||
headline="Stop chasing spreadsheets across campaigns."
|
||||
sub="Full pipeline view. Every pledge tracked. Free forever."
|
||||
/>
|
||||
<Footer active="organisations" />
|
||||
</div>
|
||||
|
||||
@@ -17,28 +17,28 @@ const PERSONAS = [
|
||||
title: "Charity Manager",
|
||||
oneLiner: "You raise pledges at events. We make sure the money actually arrives.",
|
||||
tags: ["Dashboard", "WhatsApp reminders", "Gift Aid", "Zakat", "HMRC export"],
|
||||
image: "/images/landing/08-charities-hero.jpg",
|
||||
image: "/images/landing/persona-charity-manager.jpg",
|
||||
},
|
||||
{
|
||||
slug: "organisations",
|
||||
title: "Programme Manager",
|
||||
oneLiner: "You coordinate campaigns across teams. We give you the full pipeline view.",
|
||||
tags: ["Multi-campaign", "Team oversight", "Pipeline view", "Instalments", "Reporting"],
|
||||
image: "/images/landing/persona-programme-manager.jpg",
|
||||
},
|
||||
{
|
||||
slug: "fundraisers",
|
||||
title: "Personal Fundraiser",
|
||||
oneLiner: "You share a LaunchGood or JustGiving link. We track who actually donates.",
|
||||
tags: ["LaunchGood", "Enthuse", "JustGiving", "Social sharing", "Conversion tracking"],
|
||||
image: "/images/landing/03-main-fundraiser-card.jpg",
|
||||
image: "/images/landing/persona-fundraiser.jpg",
|
||||
},
|
||||
{
|
||||
slug: "volunteers",
|
||||
title: "Volunteer",
|
||||
oneLiner: "You help collect pledges at events. We show you exactly how much you raised.",
|
||||
tags: ["Personal link", "Live stats", "Leaderboard", "WhatsApp share"],
|
||||
image: "/images/landing/04-main-volunteer-card.jpg",
|
||||
},
|
||||
{
|
||||
slug: "organisations",
|
||||
title: "Organisation",
|
||||
oneLiner: "You coordinate pledges across multiple charities or departments. We track every commitment.",
|
||||
tags: ["Multi-party", "Fund allocation", "Pipeline view", "Instalments"],
|
||||
image: "/images/landing/05-main-org-card.jpg",
|
||||
image: "/images/landing/persona-volunteer.jpg",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -130,40 +130,64 @@ export default function HomePage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ━━ PRODUCT IMAGE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */}
|
||||
<section className="pt-16 pb-8 md:pt-20 md:pb-10 px-6">
|
||||
<div className="max-w-5xl mx-auto">
|
||||
<LandingImage src="/images/landing/01-main-dashboard-hero.jpg" alt="Live pledge pipeline dashboard showing donation trends and collection status" aspect="video" />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ━━ 4 PERSONAS ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ */}
|
||||
<section className="py-24 px-6">
|
||||
<div className="max-w-5xl mx-auto space-y-14">
|
||||
<div className="max-w-2xl">
|
||||
<h2 className="text-4xl font-black text-gray-900 tracking-tight">Built for how you actually work</h2>
|
||||
<p className="text-lg text-gray-500 mt-3">Four roles. One platform. Every pledge tracked.</p>
|
||||
{/* ━━ WHO IT'S FOR — gap-px grid (signature pattern 2) ━━━━ */}
|
||||
<section className="py-20 md:py-28 px-6">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
{/* Eyebrow — border-l-2 accent (signature pattern 1) */}
|
||||
<div className="border-l-2 border-promise-blue pl-3 mb-6">
|
||||
<p className="text-[11px] font-semibold tracking-[0.15em] uppercase text-gray-500">
|
||||
Who it's for
|
||||
</p>
|
||||
</div>
|
||||
<h2 className="text-4xl md:text-5xl font-black text-gray-900 tracking-tight">
|
||||
Built for how you actually work
|
||||
</h2>
|
||||
<p className="text-lg text-gray-500 mt-3 max-w-xl">
|
||||
Four roles. One platform. Every pledge tracked.
|
||||
</p>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
{PERSONAS.map((p) => (
|
||||
{/* 2×2 gap-px grid */}
|
||||
<div className="grid md:grid-cols-2 gap-px bg-gray-200 mt-14">
|
||||
{PERSONAS.map((p, i) => (
|
||||
<Link
|
||||
key={p.slug}
|
||||
href={`/for/${p.slug}`}
|
||||
className="group block bg-white border border-gray-200 hover:border-gray-900 transition-colors"
|
||||
className="group bg-white overflow-hidden"
|
||||
>
|
||||
<LandingImage src={p.image} alt={p.title} aspect="video" />
|
||||
<div className="p-6 space-y-3">
|
||||
<h3 className="text-lg font-black text-gray-900 group-hover:text-promise-blue transition-colors">{p.title}</h3>
|
||||
<p className="text-sm text-gray-500 leading-relaxed">{p.oneLiner}</p>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{p.tags.map((t) => (
|
||||
<span key={t} className="text-[11px] font-medium text-gray-400 bg-gray-50 px-2 py-0.5">{t}</span>
|
||||
))}
|
||||
{/* Image */}
|
||||
<div className="aspect-[3/2] relative overflow-hidden">
|
||||
<Image
|
||||
src={p.image}
|
||||
alt={p.title}
|
||||
fill
|
||||
className="object-cover transition-opacity duration-300 group-hover:opacity-90"
|
||||
sizes="(max-width: 768px) 100vw, 50vw"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Text — numbered + border-l accent */}
|
||||
<div className="p-6 md:p-8">
|
||||
<div className="flex items-start gap-5">
|
||||
<span className="text-4xl font-black text-gray-100 leading-none select-none shrink-0">
|
||||
{String(i + 1).padStart(2, "0")}
|
||||
</span>
|
||||
<div className="flex-1 min-w-0 border-l-2 border-gray-900 pl-4">
|
||||
<h3 className="text-lg font-black text-gray-900 group-hover:text-promise-blue transition-colors">
|
||||
{p.title}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-500 mt-1.5 leading-relaxed">{p.oneLiner}</p>
|
||||
<div className="flex flex-wrap gap-1.5 mt-3">
|
||||
{p.tags.map((t) => (
|
||||
<span key={t} className="text-[10px] font-medium text-gray-400 bg-gray-50 px-2 py-0.5">
|
||||
{t}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-xs font-semibold text-promise-blue mt-4 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
Learn more →
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-sm font-semibold text-promise-blue opacity-0 group-hover:opacity-100 transition-opacity pt-1">
|
||||
Learn more →
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
|
||||
1
screenshots/fidya-content.html
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
BIN
screenshots/fidya-kaffarah/fidya-child-meal.jpg
Normal file
|
After Width: | Height: | Size: 662 KiB |
BIN
screenshots/fidya-kaffarah/fidya-feeding.jpg
Normal file
|
After Width: | Height: | Size: 752 KiB |
BIN
screenshots/fidya-kaffarah/fidya-quran-elder.jpg
Normal file
|
After Width: | Height: | Size: 657 KiB |
BIN
screenshots/fidya-kaffarah/kaffarah-community.jpg
Normal file
|
After Width: | Height: | Size: 778 KiB |
727
screenshots/functions.php.bak
Normal file
@@ -0,0 +1,727 @@
|
||||
<?php
|
||||
|
||||
use Manza\CharityRight\Etc;
|
||||
use Manza\CharityRight\Mappers\AppealMapper;
|
||||
use Manza\CharityRight\Theme;
|
||||
|
||||
require_once get_stylesheet_directory() . "/vendor/autoload.php";
|
||||
|
||||
// List of files which will be included.
|
||||
// You can append ! then a comma limited list of class names which must exist to that file.
|
||||
$vlTailwind_includes = array(
|
||||
'/setup.php', // Some theme setup functions
|
||||
'/template-tags.php', // Custom template tags
|
||||
'/pagination.php', // Pagination
|
||||
'/sidebars.php', // Sidebars
|
||||
'/scripts-and-styles.php', // enqueue scripts and styles
|
||||
'/page-titles.php', // page title function
|
||||
'/breadcrumbs.php', // breadcrumbs trail function
|
||||
'/acf.php', // ACF settings
|
||||
'/menus.php', // MENU inits
|
||||
'/ajax.php', // Custom AJAX returning.
|
||||
'/blocks.php', // The custom block registry.
|
||||
'/cpt.php', // Custom post type declarations
|
||||
'/blog-import.php', // Blog post importer. NOTE: Remove this once we're deployed live and happy.
|
||||
'/dashboard.php', // Configure the WP dashboard.
|
||||
'/images.php', // Configure media library images.
|
||||
"/ajax-campaigns.php", // custom AJAX campaign loader
|
||||
"/ajax-blogs.php", // custom AJAX blog loader
|
||||
'/ramadan-challenge.php', // receiving ramadan challenge appeals.
|
||||
'/team365.php', // receiving team365 appeals.
|
||||
);
|
||||
|
||||
foreach ( $vlTailwind_includes as $file ) {
|
||||
$filepath = locate_template( 'includes' . $file );
|
||||
if ( ! $filepath ) {
|
||||
trigger_error( "Error locating /includes{$file} for inclusion", E_USER_ERROR );
|
||||
}
|
||||
require_once $filepath;
|
||||
}
|
||||
|
||||
function buildHeaderTree( array &$elements, $parentId = 0 )
|
||||
{
|
||||
$branch = array();
|
||||
foreach ( $elements as &$element )
|
||||
{
|
||||
if ( $element->menu_item_parent == $parentId )
|
||||
{
|
||||
$children = buildHeaderTree( $elements, $element->ID );
|
||||
if ( $children )
|
||||
$element->wpse_children = $children;
|
||||
|
||||
$branch[$element->ID] = $element;
|
||||
unset( $element );
|
||||
}
|
||||
}
|
||||
return $branch;
|
||||
}
|
||||
|
||||
function searchSocialMedia($name, $array) {
|
||||
foreach ($array as $key => $val) {
|
||||
if ($val['name'] === $name) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
add_image_size( 'cr_card_thumb', 600, 350 , true);
|
||||
add_image_size( 'cr_large_blog_thumb', 600, 480 , true);
|
||||
|
||||
// custom excerpt length
|
||||
function wpdocs_custom_excerpt_length( $length ) {
|
||||
return 30;
|
||||
}
|
||||
add_filter( 'excerpt_length', 'wpdocs_custom_excerpt_length', 999 );
|
||||
|
||||
function new_excerpt_more( $more ) {
|
||||
return '...';
|
||||
}
|
||||
add_filter('excerpt_more', 'new_excerpt_more');
|
||||
|
||||
(new Theme)->run();
|
||||
|
||||
// Force asset URLs to use www to avoid cross-origin script/font blocking.
|
||||
add_filter( 'script_loader_src', function( $src ) {
|
||||
return str_replace( 'https://charityright.org.uk', 'https://www.charityright.org.uk', $src );
|
||||
} );
|
||||
add_filter( 'style_loader_src', function( $src ) {
|
||||
return str_replace( 'https://charityright.org.uk', 'https://www.charityright.org.uk', $src );
|
||||
} );
|
||||
|
||||
// Redirect function from author pages
|
||||
add_action('template_redirect', 'my_custom_disable_author_page');
|
||||
|
||||
function my_custom_disable_author_page() {
|
||||
global $wp_query;
|
||||
|
||||
if ( is_author() ) {
|
||||
// Redirect to homepage, set status to 301 permenant redirect.
|
||||
// Function defaults to 302 temporary redirect.
|
||||
wp_redirect(get_option('home'), 301);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
function itsme_disable_feed() {
|
||||
wp_die( __( 'No feed available, please visit the <a href="'. esc_url( home_url( '/' ) ) .'">homepage</a>!' ) );
|
||||
}
|
||||
|
||||
function disable_attachment_pages() {
|
||||
if (is_attachment()) {
|
||||
// Get the parent post ID
|
||||
$parent_post_id = wp_get_post_parent_id(get_the_ID());
|
||||
|
||||
// Redirect to parent post if available, or homepage if not
|
||||
if ($parent_post_id) {
|
||||
wp_redirect(get_permalink($parent_post_id), 301);
|
||||
} else {
|
||||
wp_redirect(home_url(), 301);
|
||||
}
|
||||
exit;
|
||||
}
|
||||
}
|
||||
add_action('template_redirect', 'disable_attachment_pages');
|
||||
|
||||
add_action('do_feed', 'itsme_disable_feed', 1);
|
||||
add_action('do_feed_rdf', 'itsme_disable_feed', 1);
|
||||
add_action('do_feed_rss', 'itsme_disable_feed', 1);
|
||||
add_action('do_feed_rss2', 'itsme_disable_feed', 1);
|
||||
add_action('do_feed_atom', 'itsme_disable_feed', 1);
|
||||
add_action('do_feed_rss2_comments', 'itsme_disable_feed', 1);
|
||||
add_action('do_feed_atom_comments', 'itsme_disable_feed', 1);
|
||||
|
||||
add_action('init', function() {
|
||||
// Add rewrite rule for campaign with query parameter
|
||||
add_rewrite_rule(
|
||||
'campaigns/([^/]+)/?$',
|
||||
'index.php?post_type=campaign&name=$matches[1]',
|
||||
'top'
|
||||
);
|
||||
|
||||
// Register your query vars
|
||||
add_filter('query_vars', function($vars) {
|
||||
$vars[] = 'p'; // Using 'p' instead of 'page'
|
||||
return $vars;
|
||||
});
|
||||
});
|
||||
|
||||
// Prevent canonical redirect
|
||||
add_filter('redirect_canonical', function($redirect_url, $requested_url) {
|
||||
if (is_singular('campaign')) {
|
||||
return false;
|
||||
}
|
||||
return $redirect_url;
|
||||
}, 10, 2);
|
||||
|
||||
// donations
|
||||
add_action('rest_api_init', function () {
|
||||
register_rest_route('charityright/v1', '/donations', [
|
||||
'methods' => 'GET',
|
||||
'callback' => 'get_external_donations',
|
||||
'permission_callback' => '__return_true', // Adjust permissions if necessary
|
||||
]);
|
||||
});
|
||||
|
||||
if (!function_exists('wp_money_format')) {
|
||||
function wp_money_format($amount, $currency_symbol = '£', $decimal_places = 2, $thousands_separator = ',', $decimal_separator = '.') {
|
||||
// Ensure the amount is a float
|
||||
$amount = floatval($amount);
|
||||
|
||||
// Format the amount
|
||||
$formatted_amount = number_format($amount, $decimal_places, $decimal_separator, $thousands_separator);
|
||||
|
||||
// Return with the currency symbol
|
||||
return $currency_symbol . $formatted_amount;
|
||||
}
|
||||
}
|
||||
|
||||
function get_external_donations($request) {
|
||||
// Define the appeal ID if necessary, otherwise, pass it from the request
|
||||
$appeal_id = $request->get_param('appeal_id');
|
||||
$page = $request->get_param('page') ?? 1;
|
||||
$per_page = 5; // Define how many donations you want per page
|
||||
|
||||
// External API URL with the appeal_id
|
||||
$url = trim(str_replace("donate", "", get_field("generic_donate_url", "options")), "/") . "/api/v1/appeal-donations/{$appeal_id}?page={$page}&per_page={$per_page}";
|
||||
|
||||
// Fetch donations from the external API
|
||||
$response = wp_remote_get($url);
|
||||
|
||||
if (is_wp_error($response)) {
|
||||
return new WP_REST_Response([
|
||||
'message' => 'Failed to fetch donations from external API',
|
||||
'error' => $response->get_error_message()
|
||||
], 500);
|
||||
}
|
||||
|
||||
$data = json_decode(wp_remote_retrieve_body($response), true);
|
||||
|
||||
if (!$data || !isset($data['data']) || !is_array($data['data'])) {
|
||||
return new WP_REST_Response([
|
||||
'message' => 'No donations found or invalid data format'
|
||||
], 404);
|
||||
}
|
||||
|
||||
|
||||
$formattedDonations = array_map(function($donation) {
|
||||
return [
|
||||
'id' => $donation['id'],
|
||||
'donor_name' => $donation['is_anonymous'] ? 'Anonymous' : $donation['donor_name'],
|
||||
'initials' => strtoupper(substr($donation['donor_name'], 0, 1)), // Extract initials
|
||||
'donated_at' => $donation['created_at'], // Pass the raw date, format on frontend
|
||||
'amount' => $donation['amount'],
|
||||
'donor_message' => $donation['donor_message'] ?? ''
|
||||
];
|
||||
}, $data['data']);
|
||||
|
||||
// Return formatted donations and pagination info
|
||||
return new WP_REST_Response([
|
||||
'donations' => $formattedDonations,
|
||||
'pagination' => [
|
||||
'current_page' => $data['current_page'],
|
||||
'last_page' => $data['last_page'],
|
||||
'total' => $data['total']
|
||||
]
|
||||
], 200);
|
||||
}
|
||||
|
||||
add_action('rest_api_init', function () {
|
||||
register_rest_route('custom/v1', '/delete-post', array(
|
||||
'methods' => 'DELETE',
|
||||
'callback' => 'handle_delete_post',
|
||||
'permission_callback' => '__return_true',
|
||||
'args' => array(
|
||||
'slug' => array(
|
||||
'required' => true,
|
||||
'validate_callback' => function($param) {
|
||||
return is_string($param); // Ensure slug is a string
|
||||
}
|
||||
),
|
||||
'api_key' => array(
|
||||
'required' => true
|
||||
)
|
||||
)
|
||||
));
|
||||
|
||||
register_rest_route('custom/v1', '/update-campaign-preview', array(
|
||||
'methods' => 'POST',
|
||||
'callback' => 'handle_update_campaign_preview',
|
||||
'permission_callback' => '__return_true',
|
||||
'args' => array(
|
||||
'slug' => array(
|
||||
'required' => true,
|
||||
'validate_callback' => function($param) {
|
||||
return is_string($param); // Ensure slug is a string
|
||||
}
|
||||
),
|
||||
'api_key' => array(
|
||||
'required' => true
|
||||
)
|
||||
)
|
||||
));
|
||||
|
||||
register_rest_route('custom/v1', '/update-strava-leaderboard', array(
|
||||
'methods' => 'POST',
|
||||
'callback' => 'handle_strava_leaderboard',
|
||||
'permission_callback' => '__return_true',
|
||||
'args' => array(
|
||||
'api_key' => array(
|
||||
'required' => true
|
||||
),
|
||||
'list' => array(
|
||||
'required' => false, // Set to true if `list` is mandatory
|
||||
'validate_callback' => function ($param, $request, $key) {
|
||||
return is_array($param); // Ensure `list` is an array
|
||||
}
|
||||
)
|
||||
)
|
||||
));
|
||||
});
|
||||
|
||||
function handle_delete_post($request) {
|
||||
// Validate API key (you should store this securely)
|
||||
$valid_api_key = 'AKDJSHF8932YRJDFKSAFH120';
|
||||
|
||||
if ($request['api_key'] !== $valid_api_key) {
|
||||
return new WP_Error(
|
||||
'invalid_api_key',
|
||||
'Invalid API key provided.',
|
||||
array('status' => 403)
|
||||
);
|
||||
}
|
||||
|
||||
// Get the slug from the request
|
||||
$slug = $request['slug'];
|
||||
|
||||
// Retrieve the post by slug
|
||||
$post = get_page_by_path($slug, OBJECT, 'campaign');
|
||||
|
||||
if (!$post) {
|
||||
return new WP_Error(
|
||||
'post_not_found',
|
||||
'Post not found',
|
||||
array('status' => 404)
|
||||
);
|
||||
}
|
||||
|
||||
// Attempt to delete the post
|
||||
$deleted = wp_delete_post($post->ID, true);
|
||||
|
||||
if (!$deleted) {
|
||||
return new WP_Error(
|
||||
'delete_failed',
|
||||
'Failed to delete post',
|
||||
array('status' => 500)
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'status' => 'success',
|
||||
'message' => 'Post deleted successfully',
|
||||
'deleted_slug' => $slug
|
||||
);
|
||||
}
|
||||
|
||||
if (!function_exists("number_shorten")) {
|
||||
/**
|
||||
* Shorten long numbers and attaches K, M, B, etc. accordingly
|
||||
* @param int $n
|
||||
* @param int $precision
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function number_shorten( $n, $precision = 1 ) {
|
||||
if ($n < 900) {
|
||||
// 0 - 900
|
||||
$n_format = number_format($n, $precision);
|
||||
$suffix = '';
|
||||
} else if ($n < 900000) {
|
||||
// 0.9k-850k
|
||||
$n_format = number_format($n / 1000, $precision);
|
||||
$suffix = 'K';
|
||||
} else if ($n < 900000000) {
|
||||
// 0.9m-850m
|
||||
$n_format = number_format($n / 1000000, $precision);
|
||||
$suffix = 'M';
|
||||
} else if ($n < 900000000000) {
|
||||
// 0.9b-850b
|
||||
$n_format = number_format($n / 1000000000, $precision);
|
||||
$suffix = 'B';
|
||||
} else {
|
||||
// 0.9t+
|
||||
$n_format = number_format($n / 1000000000000, $precision);
|
||||
$suffix = 'T';
|
||||
}
|
||||
// Remove unecessary zeroes after decimal. "1.0" -> "1"; "1.00" -> "1"
|
||||
// Intentionally does not affect partials, eg "1.50" -> "1.50"
|
||||
if ( $precision > 0 ) {
|
||||
$dotzero = '.' . str_repeat( '0', $precision );
|
||||
$n_format = str_replace( $dotzero, '', $n_format );
|
||||
}
|
||||
return $n_format . $suffix;
|
||||
}
|
||||
}
|
||||
|
||||
function handle_update_campaign_preview ($request){
|
||||
$existingPost = Etc::findPostByMeta('campaign-preview', 'appeal_id', $request['id']);
|
||||
if ($existingPost) {
|
||||
|
||||
// Update the existing post
|
||||
$postId = wp_update_post([
|
||||
'ID' => $existingPost->ID,
|
||||
'post_title' => $request['name'],
|
||||
'post_name' => $request['slug'],
|
||||
'post_content' => $request['story'],
|
||||
'post_type' => 'campaign-preview'
|
||||
]);
|
||||
|
||||
// Return the updated post object
|
||||
$campaign_preview = get_post($postId);
|
||||
} else {
|
||||
// Create a new post
|
||||
$postId = wp_insert_post([
|
||||
'post_title' => $request['name'],
|
||||
'post_name' => $request['slug'],
|
||||
'post_content' => $request['story'],
|
||||
'post_status' => 'publish',
|
||||
'post_type' => 'campaign-preview'
|
||||
]);
|
||||
error_log($postId);
|
||||
|
||||
|
||||
// Add the custom meta field for appeal_id
|
||||
add_post_meta($postId, 'appeal_id', $request['id']);
|
||||
|
||||
// Return the newly created post object
|
||||
$campaign_preview = get_post($postId);
|
||||
}
|
||||
$body = $request->get_body();
|
||||
error_log(print_r(json_decode($body, true), true));
|
||||
|
||||
foreach (AppealMapper::toACF(json_decode($body, true)) as $fieldKey => $fieldValue) {
|
||||
update_field($fieldKey, $fieldValue, $campaign_preview);
|
||||
}
|
||||
|
||||
return $campaign_preview;
|
||||
}
|
||||
|
||||
function handle_strava_leaderboard (WP_REST_Request $request){
|
||||
delete_field('strava_leaderboard', 'option');
|
||||
$list = $request->get_param('list');
|
||||
|
||||
if ($list) {
|
||||
foreach ($list as $item) {
|
||||
$row = array(
|
||||
'athlete_name' => $item['name'],
|
||||
'athlete_image' => $item['image'],
|
||||
'distance' => $item['distance']
|
||||
);
|
||||
|
||||
add_row('strava_leaderboard', $row, 'option');
|
||||
}
|
||||
} else {
|
||||
error_log('No list received.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function ajax_words_of_hope_action_submit() : void{
|
||||
$email = $_REQUEST[ "email" ];
|
||||
$name = $_REQUEST[ "name" ];
|
||||
$school = isset($_REQUEST[ "school" ]) ? $_REQUEST[ "school" ] : null;
|
||||
$form = $_REQUEST[ "form" ];
|
||||
$address = $_REQUEST[ "address" ];
|
||||
$message = $_REQUEST[ "message" ];
|
||||
$us_marketing = isset($_REQUEST[ "us_marketing" ]) ? $_REQUEST[ "us_marketing" ] : null;
|
||||
$uk_marketing = isset($_REQUEST[ "uk_marketing" ]) ? $_REQUEST[ "uk_marketing" ] : null;
|
||||
$is_in_us = $_REQUEST[ "is_in_us" ];
|
||||
|
||||
|
||||
$data = array(
|
||||
'email' => $email,
|
||||
'name' => $name,
|
||||
'school' => $school,
|
||||
'form' => $form,
|
||||
'address' => $address,
|
||||
'message' => $message,
|
||||
'us_marketing' => $us_marketing !== "on" && $is_in_us,
|
||||
'uk_marketing' => $uk_marketing == "on" && !$is_in_us,
|
||||
);
|
||||
|
||||
// Set up the arguments for the HTTP request
|
||||
$args = array(
|
||||
'method' => 'POST',
|
||||
'body' => json_encode($data),
|
||||
'headers' => array(
|
||||
'Content-Type' => 'application/json',
|
||||
),
|
||||
);
|
||||
|
||||
$base_url = trim(get_field('generic_donate_url', 'options') ?? 'http://crukv2.test/donate/', '/');
|
||||
$wohURL = str_replace("/donate", "/api/word-of-hope/store", $base_url);
|
||||
|
||||
$response = wp_remote_post($wohURL, $args);
|
||||
|
||||
|
||||
// Check for errors in the request
|
||||
if (is_wp_error($response)) {
|
||||
$error_message = $response->get_error_message();
|
||||
error_log("Error making HTTP request: $error_message");
|
||||
wp_send_json_error(array('message' => 'Error making HTTP request.'));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the response from the external API
|
||||
$response_body = wp_remote_retrieve_body($response);
|
||||
$response_code = wp_remote_retrieve_response_code($response);
|
||||
|
||||
error_log(print_r($response_body, true));
|
||||
if ($response_code === 201) {
|
||||
// Successfully submitted, return success response
|
||||
wp_send_json_success(array('message' => 'Your message has been successfully submitted.'));
|
||||
} else {
|
||||
// API returned an error, return failure response
|
||||
wp_send_json_error(array('message' => 'There was an error submitting your message.'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
add_action( "wp_ajax_words_of_hope_action", "ajax_words_of_hope_action_submit" );
|
||||
add_action( "wp_ajax_nopriv_words_of_hope_action", "ajax_words_of_hope_action_submit" );
|
||||
|
||||
// === CR Live Data: Real-time donation updates ===
|
||||
add_action('init', function() {
|
||||
\Manza\CharityRight\Endpoints\CacheBust::register();
|
||||
});
|
||||
|
||||
add_action('wp_enqueue_scripts', function() {
|
||||
if (is_singular('campaign')) {
|
||||
wp_enqueue_script('cr-live', get_template_directory_uri() . '/assets/js/cr-live.js', [], '1.0.0', true);
|
||||
}
|
||||
});
|
||||
// === End CR Live Data ===
|
||||
|
||||
// menu-fix-bust: force cache bust for gute.js
|
||||
add_filter('script_loader_src', function($src, $handle) {
|
||||
if ($handle === 'vl_new_acf_blocks') {
|
||||
$src = add_query_arg('bust', '20260218d', $src);
|
||||
}
|
||||
return $src;
|
||||
}, 10, 2);
|
||||
|
||||
|
||||
// === UTM Parameter Forwarding (2026-02-19) ===
|
||||
add_action('wp_footer', function() {
|
||||
?>
|
||||
<script>
|
||||
(function(){
|
||||
var utmParams = ['utm_source','utm_medium','utm_campaign','utm_term','utm_content','utm_id'];
|
||||
var stored = {};
|
||||
|
||||
// 1. Check URL for UTM params
|
||||
var urlParams = new URLSearchParams(window.location.search);
|
||||
var hasNew = false;
|
||||
utmParams.forEach(function(p) {
|
||||
var v = urlParams.get(p);
|
||||
if (v) { stored[p] = v; hasNew = true; }
|
||||
});
|
||||
|
||||
// 2. If new UTMs found, save to localStorage
|
||||
if (hasNew) {
|
||||
localStorage.setItem('cr_utm', JSON.stringify(stored));
|
||||
localStorage.setItem('cr_utm_ts', Date.now());
|
||||
} else {
|
||||
// 3. Load from localStorage (expire after 30 days)
|
||||
try {
|
||||
var s = localStorage.getItem('cr_utm');
|
||||
var ts = localStorage.getItem('cr_utm_ts');
|
||||
if (s && ts && (Date.now() - ts) < 30*86400000) {
|
||||
stored = JSON.parse(s);
|
||||
}
|
||||
} catch(e) {}
|
||||
}
|
||||
|
||||
// 4. Nothing stored? Exit
|
||||
if (!Object.keys(stored).length) return;
|
||||
|
||||
// 5. Append UTMs to all links pointing to app.charityright.org.uk
|
||||
function tagLinks() {
|
||||
var links = document.querySelectorAll('a[href*="app.charityright.org.uk"]');
|
||||
links.forEach(function(a) {
|
||||
try {
|
||||
var url = new URL(a.href);
|
||||
var changed = false;
|
||||
Object.keys(stored).forEach(function(k) {
|
||||
if (!url.searchParams.has(k)) {
|
||||
url.searchParams.set(k, stored[k]);
|
||||
changed = true;
|
||||
}
|
||||
});
|
||||
if (changed) a.href = url.toString();
|
||||
} catch(e) {}
|
||||
});
|
||||
}
|
||||
|
||||
// Run on load and observe DOM changes
|
||||
tagLinks();
|
||||
var observer = new MutationObserver(function() { tagLinks(); });
|
||||
observer.observe(document.body, { childList: true, subtree: true });
|
||||
})();
|
||||
</script>
|
||||
<?php
|
||||
}, 99);
|
||||
// === END UTM Parameter Forwarding ===
|
||||
|
||||
// Add padding offset class for fixed header on pages that need it
|
||||
add_filter('body_class', function($classes) {
|
||||
// Pages with their own header offset handling
|
||||
$excluded_templates = ['page-ramadan.php', 'page-fidya-kaffarah.php'];
|
||||
$template = get_page_template_slug();
|
||||
$template_file = basename(get_page_template());
|
||||
if (!in_array($template, $excluded_templates) && !in_array($template_file, $excluded_templates)) {
|
||||
$classes[] = 'cr-header-offset';
|
||||
}
|
||||
return $classes;
|
||||
});
|
||||
|
||||
// Add crossorigin="anonymous" to third-party scripts for better error reporting
|
||||
add_filter('script_loader_tag', function($tag, $handle, $src) {
|
||||
if (strpos($src, home_url()) !== false || strpos($src, '/wp-') === 0) {
|
||||
return $tag; // Skip local scripts
|
||||
}
|
||||
if (strpos($tag, 'crossorigin') !== false) {
|
||||
return $tag; // Already has crossorigin
|
||||
}
|
||||
return str_replace(' src=', ' crossorigin="anonymous" src=', $tag);
|
||||
}, 10, 3);
|
||||
|
||||
|
||||
// ══════════════════════════════════════════════════════
|
||||
// IN-APP BROWSER FIXES — SITE-WIDE
|
||||
// Fixes conversion-killing issues in Instagram, Facebook,
|
||||
// TikTok, WhatsApp, Snapchat, Twitter, Threads in-app browsers
|
||||
// ══════════════════════════════════════════════════════
|
||||
add_action("wp_head", "cr_inapp_browser_fixes", 1);
|
||||
function cr_inapp_browser_fixes() {
|
||||
?>
|
||||
<style id="cr-inapp-fixes">
|
||||
/* Prevent auto-zoom on input focus — iOS zooms on <16px inputs */
|
||||
@supports (-webkit-touch-callout: none) {
|
||||
input, select, textarea { font-size: max(16px, 1em) !important; }
|
||||
}
|
||||
/* Safe area insets for notched devices */
|
||||
body { padding-bottom: env(safe-area-inset-bottom, 0px); }
|
||||
/* Prevent text inflation in WebViews */
|
||||
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
|
||||
/* Fix rubber-banding scroll issues */
|
||||
html { overscroll-behavior-y: none; }
|
||||
/* 100vh fix — add dvh fallback globally */
|
||||
.min-h-screen, [style*="100vh"] { min-height: 100vh; min-height: 100dvh; }
|
||||
/* Minimum touch targets (WCAG 2.5.8) */
|
||||
a, button, [role="button"], input[type="submit"], input[type="button"] { min-height: 44px; }
|
||||
/* Fix Livewire/Alpine flicker in WebViews */
|
||||
[x-cloak] { display: none !important; }
|
||||
/* In-app browser banner */
|
||||
#cr-inapp-banner {
|
||||
display: none; position: fixed; bottom: 0; left: 0; right: 0; z-index: 999999;
|
||||
padding: 14px 20px calc(14px + env(safe-area-inset-bottom, 0px));
|
||||
background: rgba(26,26,46,.97); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
|
||||
border-top: 1px solid rgba(228,34,129,.25);
|
||||
text-align: center; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
}
|
||||
#cr-inapp-banner p {
|
||||
color: #fff; font-size: 13px; font-weight: 600; margin: 0 0 10px; line-height: 1.3;
|
||||
}
|
||||
#cr-inapp-banner .cr-iab-open {
|
||||
display: inline-block; padding: 11px 28px;
|
||||
background: #E42281; color: #fff !important; font-size: 13px; font-weight: 700;
|
||||
border-radius: 8px; text-decoration: none !important; min-height: 44px; line-height: 22px;
|
||||
}
|
||||
#cr-inapp-banner .cr-iab-dismiss {
|
||||
display: block; margin: 10px auto 0; background: none; border: none;
|
||||
color: rgba(255,255,255,.35); font-size: 11px; cursor: pointer; padding: 6px;
|
||||
min-height: 30px;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
|
||||
add_action("wp_body_open", "cr_inapp_browser_banner", 1);
|
||||
function cr_inapp_browser_banner() {
|
||||
?>
|
||||
<div id="cr-inapp-banner" role="complementary" aria-label="Open in browser">
|
||||
<p>For the best experience, open in your browser</p>
|
||||
<a id="cr-iab-open" class="cr-iab-open" href="#">Open in Safari ↗</a>
|
||||
<button class="cr-iab-dismiss" id="cr-iab-dismiss" aria-label="Dismiss">Continue here</button>
|
||||
</div>
|
||||
<script>
|
||||
(function(){
|
||||
if(sessionStorage.getItem("cr_iab_off")) return;
|
||||
var ua=navigator.userAgent||"";
|
||||
var isInApp=false;
|
||||
// Detect all major in-app browsers
|
||||
if(/FBAN|FBAV/i.test(ua)) isInApp=true; // Facebook
|
||||
if(/Instagram/i.test(ua)) isInApp=true; // Instagram
|
||||
if(/TikTok|BytedanceWebview|musical_ly/i.test(ua)) isInApp=true; // TikTok
|
||||
if(/Snapchat/i.test(ua)) isInApp=true; // Snapchat
|
||||
if(/Twitter|Threads/i.test(ua)) isInApp=true; // Twitter/Threads
|
||||
if(/Line\//i.test(ua)) isInApp=true; // LINE
|
||||
if(/\bwv\b|WebView/i.test(ua)) isInApp=true; // Generic Android WebView
|
||||
if(/LinkedIn/i.test(ua)) isInApp=true; // LinkedIn
|
||||
if(/Pinterest/i.test(ua)) isInApp=true; // Pinterest
|
||||
if(/Telegram/i.test(ua)) isInApp=true; // Telegram
|
||||
// iOS: has iPhone/iPad but NOT Safari = in-app WebView
|
||||
if(!isInApp&&/iPhone|iPad/.test(ua)&&!/Safari/i.test(ua)) isInApp=true;
|
||||
if(!isInApp) return;
|
||||
|
||||
var b=document.getElementById("cr-inapp-banner");
|
||||
var o=document.getElementById("cr-iab-open");
|
||||
var d=document.getElementById("cr-iab-dismiss");
|
||||
if(!b||!o) return;
|
||||
|
||||
var url=window.location.href;
|
||||
if(/iPhone|iPad|iPod/i.test(ua)){
|
||||
o.href=url; o.setAttribute("target","_blank"); o.textContent="Open in Safari ↗";
|
||||
} else {
|
||||
o.href="intent:"+url.replace(/^https?/,"")+"#Intent;scheme=https;end";
|
||||
o.textContent="Open in Chrome ↗";
|
||||
}
|
||||
b.style.display="block";
|
||||
|
||||
if(d) d.addEventListener("click",function(){
|
||||
b.style.display="none";
|
||||
sessionStorage.setItem("cr_iab_off","1");
|
||||
});
|
||||
|
||||
// CRITICAL: Intercept window.open calls and redirect to same-window
|
||||
// This fixes ALL donate buttons site-wide that use window.open
|
||||
var _origOpen = window.open;
|
||||
window.open = function(url, target) {
|
||||
if(url && typeof url === "string" && (url.indexOf("app.charityright.org.uk") > -1 || url.indexOf("/donate") > -1)) {
|
||||
// In-app browser: redirect same-window instead of popup
|
||||
window.location.href = url;
|
||||
return null;
|
||||
}
|
||||
return _origOpen.apply(window, arguments);
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
// ══════════════════════════════════════════════════════
|
||||
// PREFETCH + PRECONNECT — Speed up checkout transition
|
||||
// In-app browsers have cold DNS/TCP so this is critical
|
||||
// ══════════════════════════════════════════════════════
|
||||
add_action("wp_head", "cr_inapp_prefetch_hints", 2);
|
||||
function cr_inapp_prefetch_hints() {
|
||||
?>
|
||||
<link rel="preconnect" href="https://app.charityright.org.uk" crossorigin>
|
||||
<link rel="dns-prefetch" href="https://app.charityright.org.uk">
|
||||
<link rel="preconnect" href="https://js.stripe.com" crossorigin>
|
||||
<link rel="dns-prefetch" href="https://js.stripe.com">
|
||||
<link rel="preconnect" href="https://fonts.bunny.net" crossorigin>
|
||||
<?php
|
||||
}
|
||||
463
screenshots/page-fidya-kaffarah-updated.php
Normal file
@@ -0,0 +1,463 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: Fidya Kaffarah
|
||||
*/
|
||||
get_header();
|
||||
$site_url = get_site_url();
|
||||
$uploads = get_site_url() . '/wp-content/uploads/2026/03';
|
||||
?>
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
.fk, .fk * {
|
||||
box-sizing: border-box;
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
.fk, .fk h1, .fk h2, .fk h3, .fk h4, .fk span, .fk div, .fk p, .fk li, .fk strong, .fk .fk-amount, .fk .fk-card-label { color: #fff !important; }
|
||||
.fk {
|
||||
padding: 0 !important;
|
||||
background: #0a0a0a !important;
|
||||
color: #fff;
|
||||
}
|
||||
.fk-inner {
|
||||
max-width: 1200px;
|
||||
padding: 0 24px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Hero section with background image */
|
||||
.fk-hero {
|
||||
position: relative;
|
||||
padding: 120px 20px 80px;
|
||||
overflow: hidden;
|
||||
min-height: 480px;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
}
|
||||
.fk-hero-bg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-image: url('<?php echo $uploads; ?>/fidya-hero.jpg');
|
||||
background-size: cover;
|
||||
background-position: center 25%;
|
||||
z-index: 0;
|
||||
}
|
||||
.fk-hero-bg::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(
|
||||
to bottom,
|
||||
rgba(10,10,10,0.3) 0%,
|
||||
rgba(10,10,10,0.6) 40%,
|
||||
rgba(10,10,10,0.92) 100%
|
||||
);
|
||||
}
|
||||
.fk-hero .fk-inner {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.fk h1 {
|
||||
color: #fff !important;
|
||||
font-size: clamp(2rem, 5vw, 3.2rem);
|
||||
font-weight: 900;
|
||||
line-height: 1.1;
|
||||
margin-bottom: 12px;
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
.fk h1 span { color: #e42281 !important; }
|
||||
.fk .fk-sub {
|
||||
font-size: 1.05rem;
|
||||
color: #ccc !important;
|
||||
font-weight: 300;
|
||||
line-height: 1.6;
|
||||
max-width: 600px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* Content section */
|
||||
.fk-content {
|
||||
padding: 60px 20px 80px;
|
||||
}
|
||||
|
||||
/* Cards */
|
||||
.fk-cards {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 24px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
.fk-card {
|
||||
background: #141414;
|
||||
border: 1px solid #222;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: border-color 0.3s, background 0.3s;
|
||||
}
|
||||
.fk-card:hover {
|
||||
border-color: #e42281 !important;
|
||||
background: #1a1a1a;
|
||||
}
|
||||
|
||||
/* Card images */
|
||||
.fk-card-img {
|
||||
width: 100%;
|
||||
height: 220px;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
filter: brightness(0.85);
|
||||
transition: filter 0.3s, transform 0.4s;
|
||||
}
|
||||
.fk-card:hover .fk-card-img {
|
||||
filter: brightness(1);
|
||||
transform: scale(1.03);
|
||||
}
|
||||
.fk-card-img-wrap {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.fk-card-img-wrap::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
bottom: 0; left: 0; right: 0;
|
||||
height: 60px;
|
||||
background: linear-gradient(to bottom, transparent, #141414);
|
||||
}
|
||||
.fk-card:hover .fk-card-img-wrap::after {
|
||||
background: linear-gradient(to bottom, transparent, #1a1a1a);
|
||||
}
|
||||
|
||||
.fk-card-body {
|
||||
padding: 32px 32px 40px;
|
||||
}
|
||||
|
||||
.fk-card-label {
|
||||
font-size: 0.65rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 3px;
|
||||
color: #e42281 !important;
|
||||
margin-bottom: 20px;
|
||||
display: block;
|
||||
}
|
||||
.fk-card h2 {
|
||||
color: #fff !important;
|
||||
font-size: 1.6rem;
|
||||
font-weight: 800;
|
||||
line-height: 1.15;
|
||||
margin-bottom: 16px;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
.fk-card p {
|
||||
font-size: 0.92rem;
|
||||
color: #999 !important;
|
||||
line-height: 1.65;
|
||||
margin-bottom: 24px;
|
||||
font-weight: 300;
|
||||
}
|
||||
.fk-card .fk-amount {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.fk-card .fk-amount span {
|
||||
color: #e42281 !important;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
.fk-card .fk-calc {
|
||||
font-size: 0.82rem;
|
||||
color: #666 !important;
|
||||
margin-bottom: 28px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.fk-btn {
|
||||
display: inline-block;
|
||||
background: #e42281;
|
||||
color: #fff !important;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
padding: 14px 32px;
|
||||
text-decoration: none !important;
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
border-radius: 2px;
|
||||
transition: background 0.2s, transform 0.2s;
|
||||
}
|
||||
.fk-btn:hover {
|
||||
background: #c2185b;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.fk-btn:visited { color: #fff !important; }
|
||||
|
||||
/* Who is this for sections */
|
||||
.fk-who {
|
||||
margin-top: 20px;
|
||||
padding-top: 24px;
|
||||
border-top: 1px solid #222;
|
||||
}
|
||||
.fk-who-label {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
color: #555 !important;
|
||||
margin-bottom: 12px;
|
||||
display: block;
|
||||
}
|
||||
.fk-who ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.fk-who li {
|
||||
font-size: 0.85rem;
|
||||
color: #bbb !important;
|
||||
line-height: 1.5;
|
||||
padding: 6px 0 6px 20px;
|
||||
position: relative;
|
||||
font-weight: 400;
|
||||
}
|
||||
.fk-who li::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 12px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #e42281;
|
||||
}
|
||||
|
||||
/* Full-width image strip */
|
||||
.fk-image-strip {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 320px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
.fk-image-strip img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-position: center 30%;
|
||||
display: block;
|
||||
filter: brightness(0.7);
|
||||
}
|
||||
.fk-image-strip::before,
|
||||
.fk-image-strip::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0; right: 0;
|
||||
height: 80px;
|
||||
z-index: 1;
|
||||
}
|
||||
.fk-image-strip::before {
|
||||
top: 0;
|
||||
background: linear-gradient(to bottom, #0a0a0a, transparent);
|
||||
}
|
||||
.fk-image-strip::after {
|
||||
bottom: 0;
|
||||
background: linear-gradient(to top, #0a0a0a, transparent);
|
||||
}
|
||||
.fk-image-strip-text {
|
||||
position: absolute;
|
||||
bottom: 32px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 2;
|
||||
text-align: center;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 3px;
|
||||
color: rgba(255,255,255,0.6) !important;
|
||||
}
|
||||
|
||||
/* Not sure section */
|
||||
.fk-unsure {
|
||||
text-align: center;
|
||||
margin-bottom: 60px;
|
||||
padding: 32px;
|
||||
background: #141414;
|
||||
border: 1px solid #222;
|
||||
}
|
||||
.fk-unsure h3 {
|
||||
color: #fff !important;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
.fk-unsure p {
|
||||
font-size: 0.92rem;
|
||||
color: #999 !important;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 300;
|
||||
}
|
||||
.fk-unsure p:last-child { margin-bottom: 0; }
|
||||
.fk-unsure strong {
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Bottom quote with background */
|
||||
.fk-quote-section {
|
||||
position: relative;
|
||||
padding: 80px 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.fk-quote-bg {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-image: url('<?php echo $uploads; ?>/fidya-child-meal.jpg');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
z-index: 0;
|
||||
}
|
||||
.fk-quote-bg::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(10,10,10,0.82);
|
||||
}
|
||||
.fk-quote {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
text-align: center;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.fk-quote p {
|
||||
font-size: 1.05rem;
|
||||
color: #ccc !important;
|
||||
font-style: italic;
|
||||
line-height: 1.7;
|
||||
font-weight: 300;
|
||||
}
|
||||
.fk-quote .fk-attr {
|
||||
font-size: 0.8rem;
|
||||
color: #888 !important;
|
||||
font-style: normal;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.fk-cards {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.fk, .fk h1, .fk h2, .fk h3, .fk h4, .fk span, .fk div, .fk p, .fk li, .fk strong, .fk .fk-amount, .fk .fk-card-label { color: #fff !important; }
|
||||
.fk-hero { padding: 80px 16px 50px; min-height: 380px; }
|
||||
.fk-content { padding: 40px 16px 60px; }
|
||||
.fk-card-body { padding: 24px 24px 32px; }
|
||||
.fk-card-img { height: 180px; }
|
||||
.fk-image-strip { height: 220px; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="fk">
|
||||
|
||||
<!-- Hero with background photography -->
|
||||
<div class="fk-hero">
|
||||
<div class="fk-hero-bg"></div>
|
||||
<div class="fk-inner">
|
||||
<h1>Missed Fasts?<br><span>Make it Right.</span></h1>
|
||||
<p class="fk-sub">If you are unable to fast during Ramadan, or have broken a fast without a valid reason, Islam provides a way to fulfil your obligation. Choose the option that applies to you.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main content -->
|
||||
<div class="fk-content">
|
||||
<div class="fk-inner">
|
||||
|
||||
<div class="fk-cards">
|
||||
|
||||
<!-- FIDYA -->
|
||||
<div class="fk-card">
|
||||
<div class="fk-card-img-wrap">
|
||||
<img class="fk-card-img" src="<?php echo $uploads; ?>/fidya-quran-elder.jpg" alt="An elderly man in prayer — for those who are unable to fast" loading="lazy">
|
||||
</div>
|
||||
<div class="fk-card-body">
|
||||
<span class="fk-card-label">Fidya</span>
|
||||
<h2>I am unable to fast<br>and cannot make it up.</h2>
|
||||
<p>Fidya is a <strong style="color:#fff;font-weight:600;">compensation</strong> for those who cannot fast during Ramadan due to a long-term illness, old age, or a condition that is not expected to improve. For each day of fasting missed, you are required to feed one person in need.</p>
|
||||
|
||||
<div class="fk-amount"><span>£5</span> per missed fast</div>
|
||||
<div class="fk-calc">Feeds one person for each day you are unable to fast</div>
|
||||
|
||||
<a href="https://app.charityright.org.uk/donate/?v=2&project=18" class="fk-btn">Pay Fidya</a>
|
||||
|
||||
<div class="fk-who">
|
||||
<span class="fk-who-label">This applies if you</span>
|
||||
<ul>
|
||||
<li>Have a long-term or chronic illness with no expectation of recovery</li>
|
||||
<li>Are elderly and physically unable to fast</li>
|
||||
<li>Have a medical condition requiring daily medication that prevents fasting</li>
|
||||
<li>Have been advised by a doctor that fasting would be harmful to your health</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- KAFFARAH -->
|
||||
<div class="fk-card">
|
||||
<div class="fk-card-img-wrap">
|
||||
<img class="fk-card-img" src="<?php echo $uploads; ?>/kaffarah-community.jpg" alt="Children receiving meals at a community feeding programme" loading="lazy">
|
||||
</div>
|
||||
<div class="fk-card-body">
|
||||
<span class="fk-card-label">Kaffarah</span>
|
||||
<h2>I deliberately broke<br>my fast without reason.</h2>
|
||||
<p>Kaffarah is an <strong style="color:#fff;font-weight:600;">expiation</strong> required when a person deliberately breaks their Ramadan fast without a valid Islamic reason. The obligation is to fast for 60 consecutive days. If you are genuinely unable to do so, you must feed 60 people in need for each fast broken.</p>
|
||||
|
||||
<div class="fk-amount"><span>£300</span> per broken fast</div>
|
||||
<div class="fk-calc">Equivalent to feeding 60 people in need</div>
|
||||
|
||||
<a href="https://app.charityright.org.uk/donate/?v=2&project=28" class="fk-btn">Pay Kaffarah</a>
|
||||
|
||||
<div class="fk-who">
|
||||
<span class="fk-who-label">This applies if you</span>
|
||||
<ul>
|
||||
<li>Deliberately ate or drank during fasting hours without a valid reason</li>
|
||||
<li>Intentionally broke your fast in a way that invalidates it</li>
|
||||
<li>Are unable to fast for 60 consecutive days as the primary expiation</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Full-width image strip — feeding the hungry -->
|
||||
<div class="fk-image-strip">
|
||||
<img src="<?php echo $uploads; ?>/fidya-feeding.jpg" alt="Food being served to those in need" loading="lazy">
|
||||
<span class="fk-image-strip-text">Every meal matters</span>
|
||||
</div>
|
||||
|
||||
<div class="fk-unsure">
|
||||
<h3>Can you make up your fasts?</h3>
|
||||
<p>If you missed fasts due to a <strong>temporary</strong> illness, travel, menstruation, or pregnancy, you are expected to make up the missed days before the next Ramadan. In this case, neither Fidya nor Kaffarah is required.</p>
|
||||
<p>Fidya applies only when you are <strong>permanently unable</strong> to fast. Kaffarah applies only when you <strong>deliberately</strong> broke a fast without a valid reason. If you are unsure, consult a scholar.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Quote section with background photography -->
|
||||
<div class="fk-quote-section">
|
||||
<div class="fk-quote-bg"></div>
|
||||
<div class="fk-quote">
|
||||
<p>“And upon those who are able [to fast, but with hardship] — a ransom of feeding a poor person.”</p>
|
||||
<p class="fk-attr">— Qur’an, Surah Al-Baqarah (2:184)</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
297
screenshots/page-fidya-kaffarah.php
Normal file
@@ -0,0 +1,297 @@
|
||||
<?php
|
||||
/**
|
||||
* Template Name: Fidya Kaffarah
|
||||
*/
|
||||
get_header();
|
||||
$site_url = get_site_url();
|
||||
?>
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
|
||||
|
||||
<style>
|
||||
.fk, .fk * {
|
||||
box-sizing: border-box;
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
margin: 0; padding: 0;
|
||||
}
|
||||
.fk, .fk h1, .fk h2, .fk h3, .fk h4, .fk span, .fk div, .fk p, .fk li, .fk strong, .fk .fk-amount, .fk .fk-card-label { color: #fff !important; }
|
||||
.fk {
|
||||
padding: 76px 20px 80px !important;
|
||||
background: #0a0a0a !important;
|
||||
color: #fff;
|
||||
min-height: 100vh; height: 100dvh; min-height: 100dvh;
|
||||
}
|
||||
.fk-inner {
|
||||
max-width: 1200px;
|
||||
padding: 0 24px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.fk h1 {
|
||||
color: #fff !important;
|
||||
font-size: clamp(2rem, 5vw, 3.2rem);
|
||||
font-weight: 900;
|
||||
line-height: 1.1;
|
||||
margin-bottom: 12px;
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
.fk h1 span { color: #e42281 !important; }
|
||||
.fk .fk-sub {
|
||||
font-size: 1.05rem;
|
||||
color: #aaa !important;
|
||||
font-weight: 300;
|
||||
line-height: 1.6;
|
||||
max-width: 600px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
|
||||
/* Cards */
|
||||
.fk-cards {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 24px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
.fk-card {
|
||||
background: #141414;
|
||||
border: 1px solid #222;
|
||||
padding: 40px 32px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: border-color 0.3s, background 0.3s;
|
||||
}
|
||||
.fk-card:hover {
|
||||
border-color: #e42281 !important;
|
||||
background: #1a1a1a;
|
||||
}
|
||||
.fk-card-label {
|
||||
font-size: 0.65rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 3px;
|
||||
color: #e42281 !important;
|
||||
margin-bottom: 20px;
|
||||
display: block;
|
||||
}
|
||||
.fk-card h2 {
|
||||
color: #fff !important;
|
||||
font-size: 1.6rem;
|
||||
font-weight: 800;
|
||||
line-height: 1.15;
|
||||
margin-bottom: 16px;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
.fk-card p {
|
||||
font-size: 0.92rem;
|
||||
color: #999 !important;
|
||||
line-height: 1.65;
|
||||
margin-bottom: 24px;
|
||||
font-weight: 300;
|
||||
}
|
||||
.fk-card .fk-amount {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.fk-card .fk-amount span {
|
||||
color: #e42281 !important;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
.fk-card .fk-calc {
|
||||
font-size: 0.82rem;
|
||||
color: #666 !important;
|
||||
margin-bottom: 28px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.fk-btn {
|
||||
display: inline-block;
|
||||
background: #e42281;
|
||||
color: #fff !important;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 700;
|
||||
padding: 14px 32px;
|
||||
text-decoration: none !important;
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
border-radius: 2px;
|
||||
transition: background 0.2s, transform 0.2s;
|
||||
}
|
||||
.fk-btn:hover {
|
||||
background: #c2185b;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
.fk-btn:visited { color: #fff !important; }
|
||||
|
||||
/* Who is this for sections */
|
||||
.fk-who {
|
||||
margin-top: 20px;
|
||||
padding-top: 24px;
|
||||
border-top: 1px solid #222;
|
||||
}
|
||||
.fk-who-label {
|
||||
font-size: 0.7rem;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
color: #555 !important;
|
||||
margin-bottom: 12px;
|
||||
display: block;
|
||||
}
|
||||
.fk-who ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.fk-who li {
|
||||
font-size: 0.85rem;
|
||||
color: #bbb !important;
|
||||
line-height: 1.5;
|
||||
padding: 6px 0 6px 20px;
|
||||
position: relative;
|
||||
font-weight: 400;
|
||||
}
|
||||
.fk-who li::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 12px;
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #e42281;
|
||||
}
|
||||
|
||||
/* Bottom quote */
|
||||
.fk-quote {
|
||||
text-align: center;
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
padding-top: 40px;
|
||||
border-top: 1px solid #1a1a1a;
|
||||
}
|
||||
.fk-quote p {
|
||||
font-size: 0.95rem;
|
||||
color: #777 !important;
|
||||
font-style: italic;
|
||||
line-height: 1.7;
|
||||
font-weight: 300;
|
||||
}
|
||||
.fk-quote .fk-attr {
|
||||
font-size: 0.8rem;
|
||||
color: #555 !important;
|
||||
font-style: normal;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* Back link */
|
||||
|
||||
/* Not sure section */
|
||||
.fk-unsure {
|
||||
text-align: center;
|
||||
margin-bottom: 60px;
|
||||
padding: 32px;
|
||||
background: #141414;
|
||||
border: 1px solid #222;
|
||||
}
|
||||
.fk-unsure h3 {
|
||||
color: #fff !important;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
.fk-unsure p {
|
||||
font-size: 0.92rem;
|
||||
color: #999 !important;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 12px;
|
||||
font-weight: 300;
|
||||
}
|
||||
.fk-unsure p:last-child { margin-bottom: 0; }
|
||||
.fk-unsure strong {
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
@media (max-width: 700px) {
|
||||
.fk-cards {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
.fk, .fk h1, .fk h2, .fk h3, .fk h4, .fk span, .fk div, .fk p, .fk li, .fk strong, .fk .fk-amount, .fk .fk-card-label { color: #fff !important; }
|
||||
.fk {
|
||||
padding: 76px 20px 80px !important; padding: 40px 16px 60px; }
|
||||
.fk-card { padding: 32px 24px; }
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="fk">
|
||||
<div class="fk-inner">
|
||||
|
||||
|
||||
<h1>Missed Fasts?<br><span>Make it Right.</span></h1>
|
||||
<p class="fk-sub">If you are unable to fast during Ramadan, or have broken a fast without a valid reason, Islam provides a way to fulfil your obligation. Choose the option that applies to you.</p>
|
||||
|
||||
<div class="fk-cards">
|
||||
|
||||
<!-- FIDYA -->
|
||||
<div class="fk-card">
|
||||
<span class="fk-card-label">Fidya</span>
|
||||
<h2>I am unable to fast<br>and cannot make it up.</h2>
|
||||
<p>Fidya is a <strong style="color:#fff;font-weight:600;">compensation</strong> for those who cannot fast during Ramadan due to a long-term illness, old age, or a condition that is not expected to improve. For each day of fasting missed, you are required to feed one person in need.</p>
|
||||
|
||||
<div class="fk-amount"><span>£5</span> per missed fast</div>
|
||||
<div class="fk-calc">Feeds one person for each day you are unable to fast</div>
|
||||
|
||||
<a href="https://app.charityright.org.uk/donate/?v=2&project=18" class="fk-btn">Pay Fidya</a>
|
||||
|
||||
<div class="fk-who">
|
||||
<span class="fk-who-label">This applies if you</span>
|
||||
<ul>
|
||||
<li>Have a long-term or chronic illness with no expectation of recovery</li>
|
||||
<li>Are elderly and physically unable to fast</li>
|
||||
<li>Have a medical condition requiring daily medication that prevents fasting</li>
|
||||
<li>Have been advised by a doctor that fasting would be harmful to your health</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- KAFFARAH -->
|
||||
<div class="fk-card">
|
||||
<span class="fk-card-label">Kaffarah</span>
|
||||
<h2>I deliberately broke<br>my fast without reason.</h2>
|
||||
<p>Kaffarah is an <strong style="color:#fff;font-weight:600;">expiation</strong> required when a person deliberately breaks their Ramadan fast without a valid Islamic reason. The obligation is to fast for 60 consecutive days. If you are genuinely unable to do so, you must feed 60 people in need for each fast broken.</p>
|
||||
|
||||
<div class="fk-amount"><span>£300</span> per broken fast</div>
|
||||
<div class="fk-calc">Equivalent to feeding 60 people in need</div>
|
||||
|
||||
<a href="https://app.charityright.org.uk/donate/?v=2&project=28" class="fk-btn">Pay Kaffarah</a>
|
||||
|
||||
<div class="fk-who">
|
||||
<span class="fk-who-label">This applies if you</span>
|
||||
<ul>
|
||||
<li>Deliberately ate or drank during fasting hours without a valid reason</li>
|
||||
<li>Intentionally broke your fast in a way that invalidates it</li>
|
||||
<li>Are unable to fast for 60 consecutive days as the primary expiation</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="fk-unsure">
|
||||
<h3>Can you make up your fasts?</h3>
|
||||
<p>If you missed fasts due to a <strong>temporary</strong> illness, travel, menstruation, or pregnancy, you are expected to make up the missed days before the next Ramadan. In this case, neither Fidya nor Kaffarah is required.</p>
|
||||
<p>Fidya applies only when you are <strong>permanently unable</strong> to fast. Kaffarah applies only when you <strong>deliberately</strong> broke a fast without a valid reason. If you are unsure, consult a scholar.</p>
|
||||
</div>
|
||||
|
||||
<div class="fk-quote">
|
||||
<p>“And upon those who are able [to fast, but with hardship] — a ransom of feeding a poor person.”</p>
|
||||
<p class="fk-attr">— Qur’an, Surah Al-Baqarah (2:184)</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php get_footer(); ?>
|
||||