From fc803990920850f650985de9300a3e87dac3426e Mon Sep 17 00:00:00 2001 From: Omair Saleh Date: Tue, 3 Mar 2026 20:13:22 +0800 Subject: [PATCH] brand identity overhaul: match BRAND-IDENTITY.md across all pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Design system changes (per brand guide): - ZERO rounded-2xl/3xl remaining (was 131 instances) - ZERO bg-gradient remaining (was 25) — all solid colors - ZERO colored shadows (shadow-trust-blue, etc) — flat, no glow - ZERO backdrop-blur/glass effects — solid backgrounds - ZERO emoji in logo marks — square P logomark everywhere - ZERO decorative scale animations (group-hover:scale-105, etc) Tailwind config: - Added brand color names: midnight, promise-blue, generosity-gold, fulfilled-green, alert-red, paper - Kept legacy aliases (trust-blue, etc) for backwards compat - --radius: 0.75rem → 0.5rem (tighter corners) CSS: - Removed glass, glass-dark, card-hover, pulse-ring, bounce-gentle, confetti-fall, scale-in animations - Kept only purposeful animations: fadeUp, fadeIn, slideDown, shimmer, counter-roll - --primary tuned to match Promise Blue exactly Components: - Button: removed all colored shadows, added 'blue' variant, removed rounded from sizes - All UI components: rounded-xl/2xl → rounded-lg Pages updated (41 files): - Dashboard layout: solid header (no blur), border-l-2 active indicator, midnight logo mark - Login/Signup: paper bg (no gradient), midnight logo mark, no emoji - Pledge flow: solid color icons, no gradient progress bars - All dashboard pages: flat, sharp, editorial --- gen_images.py | 135 ------------------ .../src/app/(auth)/login/page.tsx | 70 +++++---- .../src/app/(auth)/signup/page.tsx | 50 +++---- .../src/app/dashboard/admin/page.tsx | 2 +- .../src/app/dashboard/events/[id]/page.tsx | 2 +- .../src/app/dashboard/events/page.tsx | 10 +- .../src/app/dashboard/exports/page.tsx | 4 +- .../src/app/dashboard/layout.tsx | 50 +++---- .../src/app/dashboard/loading.tsx | 10 +- .../src/app/dashboard/page.tsx | 26 ++-- .../src/app/dashboard/pledges/page.tsx | 2 +- .../src/app/dashboard/reconcile/page.tsx | 2 +- .../src/app/dashboard/settings/page.tsx | 12 +- .../src/app/dashboard/setup/page.tsx | 10 +- .../src/app/e/[slug]/page.tsx | 8 +- pledge-now-pay-later/src/app/globals.css | 117 ++++----------- .../src/app/p/[token]/loading.tsx | 4 +- .../src/app/p/[token]/page.tsx | 12 +- .../src/app/p/[token]/steps/amount-step.tsx | 14 +- .../[token]/steps/bank-instructions-step.tsx | 20 +-- .../app/p/[token]/steps/card-payment-step.tsx | 4 +- .../app/p/[token]/steps/confirmation-step.tsx | 12 +- .../app/p/[token]/steps/direct-debit-step.tsx | 18 +-- .../[token]/steps/external-redirect-step.tsx | 12 +- .../src/app/p/[token]/steps/identity-step.tsx | 36 ++--- .../src/app/p/[token]/steps/payment-step.tsx | 14 +- .../src/app/p/[token]/steps/schedule-step.tsx | 32 ++--- .../src/app/p/success/page.tsx | 8 +- .../src/app/v/[code]/page.tsx | 8 +- .../src/components/live-ticker.tsx | 2 +- .../src/components/ui/button.tsx | 25 ++-- .../src/components/ui/card.tsx | 2 +- .../src/components/ui/dialog.tsx | 2 +- .../src/components/ui/dropdown-menu.tsx | 2 +- .../src/components/ui/input.tsx | 2 +- .../src/components/ui/select.tsx | 2 +- .../src/components/ui/skeleton.tsx | 2 +- .../src/components/ui/tabs.tsx | 2 +- .../src/components/ui/textarea.tsx | 2 +- .../src/components/ui/toast.tsx | 2 +- pledge-now-pay-later/tailwind.config.ts | 8 ++ 41 files changed, 282 insertions(+), 475 deletions(-) delete mode 100644 gen_images.py diff --git a/gen_images.py b/gen_images.py deleted file mode 100644 index e88f9a5..0000000 --- a/gen_images.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python3 -"""Generate PNPL landing page images using Gemini 3 Pro Image (Nano Banana Pro).""" - -import time, base64 -from pathlib import Path -from google import genai -from google.genai import types - -API_KEY = "AIzaSyCHnesXLjPw-UgeZaQotut66bgjFdvy12E" -MODEL = "gemini-3-pro-image-preview" -OUT_DIR = Path(r"C:\Users\uldvs\Downloads\PNPL Photography") -OUT_DIR.mkdir(parents=True, exist_ok=True) - -client = genai.Client(api_key=API_KEY) - -IMAGES = [ - # ── Main page ── - ("01-main-dashboard-hero", "16:9", - "Editorial product photography of a MacBook Pro on a minimal white desk showing a charity analytics dashboard with blue bar charts and a pipeline table. Clean desk with only a coffee cup and a single pen. Soft diffused daylight from the left. Shot on Sony A7III, 50mm f/2.8, shallow depth of field on the screen edges. Muted tones, magazine editorial style. Landscape orientation 16:9 aspect ratio."), - - ("02-main-charity-manager-card", "16:9", - "Candid documentary photograph of a British-Bangladeshi woman in her 40s wearing a dark navy hijab and tailored blazer, standing at the edge of a charity gala dinner in a London hotel ballroom. She holds a tablet at her side, looking across the room. Round tables with white cloths and warm tungsten pendant lights behind her, out of focus. Shot on Leica Q2, 28mm, f/1.7, available light only, natural film grain. Skin tones warm, background amber bokeh. No eye contact with camera. Landscape orientation 16:9 aspect ratio."), - - ("03-main-fundraiser-card", "16:9", - "Street photography of a young British-Somali man in his mid-20s wearing a grey crewneck sweatshirt, walking on a London residential street and looking down at his phone screen. Overcast daylight, Victorian terraced houses soft in the background. He is mid-stride, natural posture, not posing. Shot on Fujifilm X100V, 23mm, f/2, ISO 400, slight grain. Desaturated cool tones, editorial documentary feel. Landscape orientation 16:9 aspect ratio."), - - ("04-main-volunteer-card", "16:9", - "Candid indoor photograph of a young British-Pakistani woman in her early 20s wearing a plain volunteer lanyard on a black cord, leaning across a round banquet table pointing at a small printed card on the table. Warm overhead chandelier lighting in a mosque community hall, patterned carpet floor. Other seated guests softly blurred. Shot on Canon R6, 35mm f/1.4, shallow depth of field, warm amber tones. Natural, mid-conversation moment. Landscape orientation 16:9 aspect ratio."), - - ("05-main-org-card", "16:9", - "Documentary photograph of four people seated around a plain rectangular table in a small community centre meeting room. Mixed British ethnicities, business casual clothing. One person gestures at printed papers on the table, others listening. Overhead fluorescent strip lights mixed with grey window daylight. Institutional beige walls, a whiteboard partially visible behind. Shot on Nikon Z6, 28mm f/2.8, natural exposure, slightly flat lighting. No one looking at camera, mid-discussion. Landscape orientation 16:9 aspect ratio."), - - ("06-main-pledge-form", "1:1", - "Close-up over-the-shoulder photograph of a person holding an iPhone in their right hand at a dinner table. Screen shows a clean white mobile form with toggle switches and a green button, content not readable. A glass of water and folded linen napkin on the dark tablecloth beside the hand. Warm tungsten ambient light. Face not visible, only shoulder, arm, and hand in frame. Shot on 85mm f/1.8, tight crop, shallow depth of field on the screen. Natural skin tones, no flash. Square 1:1 aspect ratio."), - - ("07-main-schedule-step", "1:1", - "Overhead 45-degree photograph of a woman's hands holding a smartphone at a kitchen table. Soft morning window light from the left casting a gentle shadow. A ceramic mug of tea and a small plate with toast crumbs slightly out of focus behind the phone. The phone screen is bright white with blue accent elements, not readable. Domestic setting, wooden table surface. Shot on 50mm f/2.0, natural light only, warm muted tones. Quiet, everyday moment. Square 1:1 aspect ratio."), - - # ── Charities page ── - ("08-charities-hero", "1:1", - "Documentary portrait of a British-Bangladeshi man in his 50s wearing a white embroidered kufi cap, silver-framed reading glasses, and a pressed light blue shirt. He is seated at a side table during a mosque fundraising event, looking at an open laptop screen. Behind him, blurred rows of seated attendees in a large hall with green and gold decorations. Warm interior lighting, patterned Islamic geometric carpet visible on the floor. Shot on 56mm f/1.2, available light, rich warm tones, film grain. Candid, absorbed in his work. Square 1:1 aspect ratio."), - - ("09-charities-amount-selection", "1:1", - "Flat lay photograph of a hand holding an iPhone face-up on a dark navy tablecloth. The thumb hovers just above the bright screen. Visible beside the phone: silver cutlery, the edge of a white dinner plate, a printed menu card, and a glass of still water. Shot from directly above, 35mm, f/4, tungsten warm lighting from overhead chandeliers. The screen shows large numbers and a blue button, not readable. Charity dinner table setting, elegant but modest. Square 1:1 aspect ratio."), - - ("10-charities-whatsapp", "16:9", - "Candid photograph of a woman's hand holding a phone on her lap while sitting on a grey fabric sofa at home. The phone screen shows green WhatsApp message bubbles, text not readable. She wears a loose cardigan sleeve and a simple watch. A cushion and part of a wooden bookshelf with books visible softly in the background. Afternoon window daylight, warm golden hour tones. Shot on 50mm f/1.8, eye-level, shallow depth of field. Domestic, relaxed, real. Landscape orientation 16:9 aspect ratio."), - - # ── Fundraisers page ── - ("11-fundraisers-hero", "1:1", - "Street photography of a young British-Arab woman in her late 20s wearing a patterned burgundy hijab and a denim jacket, standing on a London high street and holding her phone screen towards a friend. The friend is partially visible and out of focus on the right edge of frame. Overcast flat daylight, shop fronts with awnings blurred behind. She is mid-laugh, natural expression. Shot on 85mm f/1.4, compressed background bokeh, desaturated cool tones with warm skin. Unstaged genuine interaction. Square 1:1 aspect ratio."), - - ("12-fundraisers-redirect", "1:1", - "Close-up of two hands holding a phone in a cafe. The screen shows a green-themed webpage with a large rounded button, generic and not readable. A marble cafe table surface with a flat white coffee in a ceramic cup and a torn croissant on a small plate beside the phone. Natural soft window light from the right. Shot on 50mm f/2.0, shallow depth of field focused on the phone screen. Warm cafe tones, European coffee shop atmosphere. No face visible. Square 1:1 aspect ratio."), - - ("13-fundraisers-dashboard", "16:9", - "Editorial product photography of a laptop screen showing a minimal analytics dashboard with a horizontal funnel chart in shades of blue, grey number cards across the top, and a simple data table below. The laptop sits on a clean white desk. Beside it, a small potted succulent and a closed notebook. Soft even studio lighting, no harsh shadows. Shot on 50mm f/4, sharp focus on screen, edges of laptop slightly soft. Clean, SaaS product marketing style. Landscape orientation 16:9 aspect ratio."), - - # ── Volunteers page ── - ("14-volunteers-hero", "1:1", - "Candid photograph of a young British-Pakistani man in his early 20s standing behind a round banquet table at a charity dinner. He wears a plain navy polo shirt and a clear plastic lanyard with a printed name badge. In the sharp foreground, a small clear acrylic A-frame stand with a QR code printed on white card sits on the white tablecloth. The volunteer is smiling at someone off-camera to the left. Background shows other round tables and warm pendant lighting, all soft and blurred. Shot on 35mm f/1.4 from table height, warm amber tones, available light. Energetic, genuine. Square 1:1 aspect ratio."), - - ("15-volunteers-phone-stats", "1:1", - "Dynamic low-angle photograph of a volunteer's torso and hand holding a phone at waist height. A black lanyard with a badge hangs from their neck, visible at the top of frame. The phone screen is bright showing a large number and a progress bar in blue, not readable. Behind and above, blurred figures walking through an event hall with overhead spotlights creating flare. Shot on 24mm f/2.0, slightly tilted angle, motion blur on background figures, available light. Raw, energetic, in-the-moment. Square 1:1 aspect ratio."), - - ("16-volunteers-leaderboard", "16:9", - "Editorial product photography of a phone screen showing a ranked list with numbered rows, small circular avatar placeholders, names, and bar charts beside each row. The phone lies flat on a dark surface. A lanyard and a paper name badge sit beside it. Soft directional studio light from the top left. Shot on macro lens, f/4, sharp focus on the screen, surroundings slightly dark. Clean, focused, app showcase. Landscape orientation 16:9 aspect ratio."), - - # ── Organisations page ── - ("17-orgs-hero-boardroom", "1:1", - "Documentary photograph of three people in a modest charity office meeting room around a rectangular table. A Black British woman in her 40s in a navy blazer is pointing at a laptop screen. A South Asian man in his 30s in a grey suit leans in to look. A white British man in his 50s in a rolled-sleeve shirt sits across, arms folded, listening. Papers and printed spreadsheets on the table. Grey carpet, a window with vertical blinds letting in flat daylight. Overhead fluorescent lighting. Shot on 28mm f/2.8, documentary wide angle, no one looking at camera, mid-discussion. Slightly cool tones, institutional setting. Square 1:1 aspect ratio."), - - ("18-orgs-pipeline", "1:1", - "Editorial product photography of a laptop screen showing a Kanban-style board with three columns of cards in white, each card showing a name, a currency amount, and a coloured status dot. The laptop is a MacBook on a plain wooden desk. A pair of reading glasses and a printed agenda document sit beside it. Soft even natural light from a window. Shot on 50mm f/3.5, focused on the screen, desk edges slightly out of focus. Neutral professional tones. Square 1:1 aspect ratio."), - - ("19-orgs-instalment-schedule", "16:9", - "Editorial product photography of a laptop screen showing a timeline or calendar view with monthly markers and progress bars in blue and grey. The laptop sits on a white conference table. Two chairs partially visible on either side, slightly blurred. A glass of water and a pen on the table. Clean fluorescent overhead lighting, even exposure. Shot on 35mm f/4, sharp focus on screen. Corporate clean, minimal, informational. Landscape orientation 16:9 aspect ratio."), - - ("20-orgs-laptop-desk", "1:1", - "Documentary photograph of a laptop open on a cluttered but real charity office desk. The screen shows a table with rows of data, not readable. A hand rests on the trackpad, wearing a simple watch. On the desk: a white ceramic mug with a tea bag tag hanging over the edge, a stack of manila folders, a small framed family photo, a desk lamp switched on. Mixed warm desk lamp light and cool daylight from a window on the right. Shot on 35mm f/2.0, focused on the laptop and hand, background slightly soft. Warm, lived-in, working moment. Square 1:1 aspect ratio."), -] - -def generate_image(filename, aspect, prompt): - out_path = OUT_DIR / f"{filename}.jpg" - if out_path.exists(): - print(f" SKIP (exists): {filename}") - return True - - print(f" Generating: {filename} ({aspect})...") - - try: - response = client.models.generate_content( - model=MODEL, - contents=prompt, - config=types.GenerateContentConfig( - response_modalities=["IMAGE", "TEXT"], - ), - ) - - for part in response.candidates[0].content.parts: - if part.inline_data: - img_bytes = part.inline_data.data - with open(out_path, "wb") as f: - f.write(img_bytes) - size_kb = len(img_bytes) / 1024 - print(f" DONE: {filename} ({size_kb:.0f} KB)") - return True - - print(f" FAIL: {filename} - no image in response") - return False - - except Exception as e: - print(f" ERROR: {filename} - {e}") - return False - - -if __name__ == "__main__": - print(f"Model: {MODEL} (Nano Banana Pro)") - print(f"Output: {OUT_DIR}") - print(f"Images: {len(IMAGES)}") - print() - - ok = 0 - fail = 0 - for i, (fn, asp, pr) in enumerate(IMAGES, 1): - print(f"[{i}/{len(IMAGES)}]") - if generate_image(fn, asp, pr): - ok += 1 - else: - fail += 1 - if i < len(IMAGES): - time.sleep(5) - - print(f"\nDone: {ok} generated, {fail} failed") - print(f"Files in: {OUT_DIR}") diff --git a/pledge-now-pay-later/src/app/(auth)/login/page.tsx b/pledge-now-pay-later/src/app/(auth)/login/page.tsx index bb89d74..c93c674 100644 --- a/pledge-now-pay-later/src/app/(auth)/login/page.tsx +++ b/pledge-now-pay-later/src/app/(auth)/login/page.tsx @@ -33,58 +33,56 @@ function LoginForm() { } } - // Auto-login as demo if ?demo=1 // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => { if (isDemo) doLogin(undefined, "demo@pnpl.app", "demo1234") }, []) return ( -
-
+
+
{isDemo && ( -
-
- 🤲 +
+
+ P
-

Loading demo...

+

Loading demo...

)} {!isDemo && ( <> -
-
- 🤲 +
+
+ P +
+
+

Welcome back

+

Sign in to your charity dashboard

-

Welcome back

-

Sign in to your charity dashboard

- {/* Social login */} -
- -
+ {/* Google */} +
-
-
or sign in with email
+
+
or sign in with email
- {/* Email/password form */}
doLogin(e)} className="space-y-3"> {error && ( -
{error}
+
{error}
)} setEmail(e.target.value)} - className="w-full rounded-xl border border-gray-200 px-4 py-3 text-sm focus:border-trust-blue focus:ring-2 focus:ring-trust-blue/20 outline-none transition-all" + className="w-full border border-gray-200 px-4 py-3 text-sm focus:border-promise-blue focus:ring-1 focus:ring-promise-blue/20 outline-none transition-colors" placeholder="Email" required /> @@ -92,36 +90,36 @@ function LoginForm() { type="password" value={password} onChange={(e) => setPassword(e.target.value)} - className="w-full rounded-xl border border-gray-200 px-4 py-3 text-sm focus:border-trust-blue focus:ring-2 focus:ring-trust-blue/20 outline-none transition-all" + className="w-full border border-gray-200 px-4 py-3 text-sm focus:border-promise-blue focus:ring-1 focus:ring-promise-blue/20 outline-none transition-colors" placeholder="Password" required />
-
-
or
+
+
or
-

+

Don't have an account?{" "} - Get Started Free + Get Started Free

)} @@ -132,7 +130,7 @@ function LoginForm() { export default function LoginPage() { return ( -
}> +
}>
) diff --git a/pledge-now-pay-later/src/app/(auth)/signup/page.tsx b/pledge-now-pay-later/src/app/(auth)/signup/page.tsx index 8e3cd94..00b0f73 100644 --- a/pledge-now-pay-later/src/app/(auth)/signup/page.tsx +++ b/pledge-now-pay-later/src/app/(auth)/signup/page.tsx @@ -38,7 +38,6 @@ export default function SignupPage() { return } - // Auto sign in and go straight to dashboard const result = await signIn("credentials", { email, password, redirect: false }) if (result?.error) { setError("Account created — please sign in") @@ -54,86 +53,83 @@ export default function SignupPage() { if (step === "loading") { return ( -
+
-
- 🤲 +
+ P
-

Setting up your charity...

+

Setting up your charity...

) } return ( -
-
-
-
- 🤲 +
+
+
+
+ P +
+
+

Start collecting pledges

+

Free. 30 seconds. No card.

-

Start collecting pledges

-

Free. 30 seconds. No card.

- {/* Google signup */}
-
-
or use email
+
+
or use email
{error && ( -
{error}
+
{error}
)} - setCharityName(e.target.value)} - className="w-full rounded-xl border border-gray-200 px-4 py-3 text-sm focus:border-trust-blue focus:ring-2 focus:ring-trust-blue/20 outline-none transition-all" + className="w-full border border-gray-200 px-4 py-3 text-sm focus:border-promise-blue focus:ring-1 focus:ring-promise-blue/20 outline-none transition-colors" placeholder="Your charity or mosque name" required autoFocus /> - setEmail(e.target.value)} - className="w-full rounded-xl border border-gray-200 px-4 py-3 text-sm focus:border-trust-blue focus:ring-2 focus:ring-trust-blue/20 outline-none transition-all" + className="w-full border border-gray-200 px-4 py-3 text-sm focus:border-promise-blue focus:ring-1 focus:ring-promise-blue/20 outline-none transition-colors" placeholder="Your email" required /> - setPassword(e.target.value)} - className="w-full rounded-xl border border-gray-200 px-4 py-3 text-sm focus:border-trust-blue focus:ring-2 focus:ring-trust-blue/20 outline-none transition-all" + className="w-full border border-gray-200 px-4 py-3 text-sm focus:border-promise-blue focus:ring-1 focus:ring-promise-blue/20 outline-none transition-colors" placeholder="Pick a password (8+ chars)" required minLength={8} /> -
-

- Already have an account? Sign in +

+ Already have an account? Sign in

diff --git a/pledge-now-pay-later/src/app/dashboard/admin/page.tsx b/pledge-now-pay-later/src/app/dashboard/admin/page.tsx index 72bc45e..ac1cd5d 100644 --- a/pledge-now-pay-later/src/app/dashboard/admin/page.tsx +++ b/pledge-now-pay-later/src/app/dashboard/admin/page.tsx @@ -93,7 +93,7 @@ export default function AdminPage() {
{Object.entries(data.byStatus).map(([status, { count, amount }]) => ( -
+
{status}

{count}

{fmt(amount)}

diff --git a/pledge-now-pay-later/src/app/dashboard/events/[id]/page.tsx b/pledge-now-pay-later/src/app/dashboard/events/[id]/page.tsx index 77ba007..8b7f7ee 100644 --- a/pledge-now-pay-later/src/app/dashboard/events/[id]/page.tsx +++ b/pledge-now-pay-later/src/app/dashboard/events/[id]/page.tsx @@ -141,7 +141,7 @@ export default function CampaignLinksPage() { {/* QR Code — compact */} -
+
diff --git a/pledge-now-pay-later/src/app/dashboard/events/page.tsx b/pledge-now-pay-later/src/app/dashboard/events/page.tsx index ccea5f5..8b9c181 100644 --- a/pledge-now-pay-later/src/app/dashboard/events/page.tsx +++ b/pledge-now-pay-later/src/app/dashboard/events/page.tsx @@ -250,7 +250,7 @@ export default function EventsPage() {
{form.paymentMode === "external" && ( -
+
@@ -285,7 +285,7 @@ export default function EventsPage() { Configure your organisation's payment details and integrations

- {error &&
{error}
} + {error &&
{error}
} {/* WhatsApp — MOST IMPORTANT, first */} @@ -194,7 +194,7 @@ function WhatsAppPanel() {
-
+
@@ -240,7 +240,7 @@ function WhatsAppPanel() {
{/* Crop to QR area: the screenshot shows full WhatsApp web page. QR code is roughly in center. We use overflow hidden + object positioning. */} -
+
{/* eslint-disable-next-line @next/next/no-img-element */}
) : ( -
+
)} @@ -285,9 +285,9 @@ function WhatsAppPanel() { -
+
-
+
diff --git a/pledge-now-pay-later/src/app/dashboard/setup/page.tsx b/pledge-now-pay-later/src/app/dashboard/setup/page.tsx index 155b68a..86908c7 100644 --- a/pledge-now-pay-later/src/app/dashboard/setup/page.tsx +++ b/pledge-now-pay-later/src/app/dashboard/setup/page.tsx @@ -125,7 +125,7 @@ export default function SetupPage() {
{steps.map((s, i) => (
-
= s.num ? "bg-trust-blue text-white" : "bg-gray-100 text-gray-400" }`}> {step > s.num ? : } @@ -231,14 +231,14 @@ export default function SetupPage() { {step === 4 && ( -
+
You're All Set! 🎉

Your charity is ready to collect pledges.

-
+
Charity {orgName} @@ -254,7 +254,7 @@ export default function SetupPage() {
{setupResult?.qrToken && ( -
+

Your pledge link is ready

@@ -278,7 +278,7 @@ export default function SetupPage() { {/* Tips */} {step < 4 && ( -
+

💡 Tip

{step === 1 &&

Your charity name appears on the donor pledge page and WhatsApp receipts.

} {step === 2 &&

Bank details are shown to donors who choose "Bank Transfer". Each pledge gets a unique reference number for easy reconciliation.

} diff --git a/pledge-now-pay-later/src/app/e/[slug]/page.tsx b/pledge-now-pay-later/src/app/e/[slug]/page.tsx index fc1998a..d9ccecd 100644 --- a/pledge-now-pay-later/src/app/e/[slug]/page.tsx +++ b/pledge-now-pay-later/src/app/e/[slug]/page.tsx @@ -82,7 +82,7 @@ export default function PublicEventPage() { if (loading) { return ( -
+
) @@ -90,7 +90,7 @@ export default function PublicEventPage() { if (error || !data) { return ( -
+

Event not found

@@ -106,7 +106,7 @@ export default function PublicEventPage() { const giftAidBonus = Math.round(data.stats.totalPledged * 0.25 * (data.stats.giftAidCount / Math.max(1, data.stats.pledgeCount))) return ( -
+
{/* Header */}
@@ -146,7 +146,7 @@ export default function PublicEventPage() {
diff --git a/pledge-now-pay-later/src/app/globals.css b/pledge-now-pay-later/src/app/globals.css index 0650615..01b6538 100644 --- a/pledge-now-pay-later/src/app/globals.css +++ b/pledge-now-pay-later/src/app/globals.css @@ -7,25 +7,25 @@ @layer base { :root { --background: 0 0% 100%; - --foreground: 222.2 84% 4.9%; + --foreground: 222 47% 11%; --card: 0 0% 100%; - --card-foreground: 222.2 84% 4.9%; + --card-foreground: 222 47% 11%; --popover: 0 0% 100%; - --popover-foreground: 222.2 84% 4.9%; - --primary: 221.2 83.2% 53.3%; - --primary-foreground: 210 40% 98%; - --secondary: 210 40% 96.1%; - --secondary-foreground: 222.2 47.4% 11.2%; - --muted: 210 40% 96.1%; - --muted-foreground: 215.4 16.3% 46.9%; - --accent: 210 40% 96.1%; - --accent-foreground: 222.2 47.4% 11.2%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 210 40% 98%; - --border: 214.3 31.8% 91.4%; - --input: 214.3 31.8% 91.4%; - --ring: 221.2 83.2% 53.3%; - --radius: 0.75rem; + --popover-foreground: 222 47% 11%; + --primary: 224 76% 40%; + --primary-foreground: 0 0% 100%; + --secondary: 220 14% 96%; + --secondary-foreground: 222 47% 11%; + --muted: 220 14% 96%; + --muted-foreground: 215 16% 47%; + --accent: 220 14% 96%; + --accent-foreground: 222 47% 11%; + --destructive: 0 72% 51%; + --destructive-foreground: 0 0% 100%; + --border: 220 13% 91%; + --input: 220 13% 91%; + --ring: 224 76% 40%; + --radius: 0.5rem; } * { @@ -45,9 +45,9 @@ } } -/* Premium animations */ +/* Animations — subtle, purposeful */ @keyframes fadeUp { - from { opacity: 0; transform: translateY(12px); } + from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } @@ -56,55 +56,32 @@ to { opacity: 1; } } -@keyframes scaleIn { - from { opacity: 0; transform: scale(0.9); } - to { opacity: 1; transform: scale(1); } -} - @keyframes slideDown { - from { opacity: 0; transform: translateY(-8px); } + from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } } -@keyframes pulse-ring { - 0% { transform: scale(0.8); opacity: 1; } - 100% { transform: scale(2); opacity: 0; } -} - @keyframes shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } } -@keyframes confetti-fall { - 0% { transform: translateY(-10vh) rotate(0deg); opacity: 1; } - 100% { transform: translateY(100vh) rotate(720deg); opacity: 0; } -} - -@keyframes bounce-gentle { - 0%, 100% { transform: translateY(0); } - 50% { transform: translateY(-4px); } -} - @keyframes counter-roll { from { transform: translateY(100%); opacity: 0; } to { transform: translateY(0); opacity: 1; } } -.animate-fade-up { animation: fadeUp 0.5s ease-out forwards; } +.animate-fade-up { animation: fadeUp 0.4s ease-out forwards; } .animate-fade-in { animation: fadeIn 0.3s ease-out forwards; } -.animate-scale-in { animation: scaleIn 0.3s ease-out forwards; } .animate-slide-down { animation: slideDown 0.3s ease-out forwards; } -.animate-pulse-ring { animation: pulse-ring 1.5s ease-out infinite; } .animate-shimmer { background: linear-gradient(90deg, transparent 30%, rgba(255,255,255,0.4) 50%, transparent 70%); background-size: 200% 100%; animation: shimmer 2s infinite; } -.animate-bounce-gentle { animation: bounce-gentle 2s ease-in-out infinite; } .animate-counter-roll { animation: counter-roll 0.4s ease-out forwards; } -/* Stagger children animations */ +/* Stagger children */ .stagger-children > * { opacity: 0; animation: fadeUp 0.4s ease-out forwards; } .stagger-children > *:nth-child(1) { animation-delay: 0ms; } .stagger-children > *:nth-child(2) { animation-delay: 60ms; } @@ -112,34 +89,6 @@ .stagger-children > *:nth-child(4) { animation-delay: 180ms; } .stagger-children > *:nth-child(5) { animation-delay: 240ms; } .stagger-children > *:nth-child(6) { animation-delay: 300ms; } -.stagger-children > *:nth-child(7) { animation-delay: 360ms; } -.stagger-children > *:nth-child(8) { animation-delay: 420ms; } - -/* Glass effects */ -.glass { - background: rgba(255, 255, 255, 0.7); - backdrop-filter: blur(20px); - -webkit-backdrop-filter: blur(20px); - border: 1px solid rgba(255, 255, 255, 0.3); -} - -.glass-dark { - background: rgba(0, 0, 0, 0.5); - backdrop-filter: blur(20px); - -webkit-backdrop-filter: blur(20px); -} - -/* Premium card hover */ -.card-hover { - transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); -} -.card-hover:hover { - transform: translateY(-2px); - box-shadow: 0 12px 40px -8px rgba(0,0,0,0.12); -} -.card-hover:active { - transform: translateY(0) scale(0.98); -} /* Number input clean */ input[type="number"]::-webkit-inner-spin-button, @@ -151,20 +100,10 @@ input[type="number"] { -moz-appearance: textfield; } -/* Scrollbar */ -::-webkit-scrollbar { - width: 4px; -} -::-webkit-scrollbar-track { - background: transparent; -} -::-webkit-scrollbar-thumb { - background: hsl(var(--muted)); - border-radius: 2px; -} +/* Scrollbar — thin, unobtrusive */ +::-webkit-scrollbar { width: 4px; } +::-webkit-scrollbar-track { background: transparent; } +::-webkit-scrollbar-thumb { background: #d1d5db; border-radius: 2px; } -/* Selection */ -::selection { - background: #1e40af20; - color: #1e40af; -} +/* Selection — brand blue */ +::selection { background: #1e40af15; color: #1e40af; } diff --git a/pledge-now-pay-later/src/app/p/[token]/loading.tsx b/pledge-now-pay-later/src/app/p/[token]/loading.tsx index a53730b..287eb94 100644 --- a/pledge-now-pay-later/src/app/p/[token]/loading.tsx +++ b/pledge-now-pay-later/src/app/p/[token]/loading.tsx @@ -1,8 +1,8 @@ export default function PledgeLoading() { return ( -
+
-
+

Loading pledge page...

diff --git a/pledge-now-pay-later/src/app/p/[token]/page.tsx b/pledge-now-pay-later/src/app/p/[token]/page.tsx index 04c9323..9275e68 100644 --- a/pledge-now-pay-later/src/app/p/[token]/page.tsx +++ b/pledge-now-pay-later/src/app/p/[token]/page.tsx @@ -189,8 +189,8 @@ export default function PledgePage() { if (loading) { return ( -
-
+
+
🤲

Loading...

@@ -200,7 +200,7 @@ export default function PledgePage() { if (error) { return ( -
+
😔

Something went wrong

@@ -260,11 +260,11 @@ export default function PledgePage() { const progressPercent = progressMap[step] || 10 return ( -
+
{/* Progress bar */}
@@ -282,7 +282,7 @@ export default function PledgePage() { {/* Back button */} {backableSteps.has(step) && ( -
+
@@ -223,7 +223,7 @@ export function BankInstructionsStep({ pledge, amount, eventName, donorPhone }:
{/* Open banking app hint */} -
+

Open your banking app → New payment → Paste the details diff --git a/pledge-now-pay-later/src/app/p/[token]/steps/card-payment-step.tsx b/pledge-now-pay-later/src/app/p/[token]/steps/card-payment-step.tsx index 4ce1321..e112806 100644 --- a/pledge-now-pay-later/src/app/p/[token]/steps/card-payment-step.tsx +++ b/pledge-now-pay-later/src/app/p/[token]/steps/card-payment-step.tsx @@ -171,7 +171,7 @@ export function CardPaymentStep({ amount, eventName, eventId, qrSourceId, onComp

{/* Card form */} -
+
{/* Card number */}
@@ -261,7 +261,7 @@ export function CardPaymentStep({ amount, eventName, eventId, qrSourceId, onComp
{/* Gift Aid */} -