MotorSignal-App/website/components/founder-portal/founder-profile-editor.tsx

656 lines
32 KiB
TypeScript

'use client';
import React, { useState } from 'react';
import Link from 'next/link';
import { Club, UserPortalPermissions } from './types';
import { updateClubProfile, sanitizePortalError } from '../../lib/club-data';
interface FounderProfileEditorProps {
club: Club;
permissions: UserPortalPermissions;
callerUid?: string;
isDemoFixture?: boolean;
onProfileUpdated?: (updated: Partial<Club>) => void;
}
export function FounderProfileEditor({
club,
permissions,
callerUid,
isDemoFixture = false,
onProfileUpdated,
}: FounderProfileEditorProps) {
// Form fields matching Section 1 & 2
const [name, setName] = useState(club.name || '');
const [description, setDescription] = useState(club.description || '');
const [homeRegion, setHomeRegion] = useState(club.homeRegion || '');
const [motorcycleFocus, setMotorcycleFocus] = useState(club.motorcycleFocus || '');
const [logoUrl, setLogoUrl] = useState(club.logoUrl || '');
const [bannerUrl, setBannerUrl] = useState(club.bannerUrl || '');
// Save states
const [isSaving, setIsSaving] = useState(false);
const [saveStatus, setSaveStatus] = useState<'idle' | 'success' | 'error'>('idle');
const [errorMessage, setErrorMessage] = useState<string | null>(null);
// Image URL validation (HTTPS only or empty to clear)
function isValidHttpsImageUrl(url: string): boolean {
const trimmed = url.trim();
if (!trimmed) return true;
try {
const parsed = new URL(trimmed);
return parsed.protocol === 'https:';
} catch {
return false;
}
}
// Validation
const trimmedName = name.trim();
const isNameValid = trimmedName.length >= 3 && trimmedName.length <= 50;
const isDescValid = description.trim().length <= 500;
const isRegionValid = homeRegion.trim().length <= 100;
const isFocusValid = motorcycleFocus.trim().length <= 100;
const isLogoUrlValid = isValidHttpsImageUrl(logoUrl);
const isBannerUrlValid = isValidHttpsImageUrl(bannerUrl);
const canSave =
isNameValid &&
isDescValid &&
isRegionValid &&
isFocusValid &&
isLogoUrlValid &&
isBannerUrlValid &&
!isSaving &&
permissions.canManageSettings;
const isDirty =
trimmedName !== (club.name || '').trim() ||
description.trim() !== (club.description || '').trim() ||
homeRegion.trim() !== (club.homeRegion || '').trim() ||
motorcycleFocus.trim() !== (club.motorcycleFocus || '').trim() ||
logoUrl.trim() !== (club.logoUrl || '').trim() ||
bannerUrl.trim() !== (club.bannerUrl || '').trim();
// Short initials for preview emblem
const initials = name
.split(/\s+/)
.filter(Boolean)
.map((w) => w[0].toUpperCase())
.slice(0, 3)
.join('') || 'MSR';
async function handleSave(e: React.FormEvent) {
e.preventDefault();
if (!canSave) return;
setIsSaving(true);
setSaveStatus('idle');
setErrorMessage(null);
const trimmedLogo = logoUrl.trim();
const trimmedBanner = bannerUrl.trim();
try {
if (isDemoFixture) {
// Simulated latency in development demo preview mode
await new Promise((resolve) => setTimeout(resolve, 600));
setSaveStatus('success');
onProfileUpdated?.({
name: trimmedName,
description: description.trim(),
homeRegion: homeRegion.trim(),
motorcycleFocus: motorcycleFocus.trim(),
logoUrl: trimmedLogo || null,
bannerUrl: trimmedBanner || null,
});
} else {
if (!callerUid) {
throw new Error('Authentication required to save profile.');
}
await updateClubProfile(club.id, callerUid, {
name: trimmedName,
description: description.trim(),
homeRegion: homeRegion.trim(),
motorcycleFocus: motorcycleFocus.trim(),
logoUrl: trimmedLogo,
bannerUrl: trimmedBanner,
});
setSaveStatus('success');
onProfileUpdated?.({
name: trimmedName,
description: description.trim(),
homeRegion: homeRegion.trim(),
motorcycleFocus: motorcycleFocus.trim(),
logoUrl: trimmedLogo || null,
bannerUrl: trimmedBanner || null,
});
}
} catch (err) {
setSaveStatus('error');
setErrorMessage(sanitizePortalError(err, 'Failed to update club profile. Please try again.'));
} finally {
setIsSaving(false);
}
}
return (
<div className="max-w-6xl mx-auto space-y-6 pb-12">
{/* 3. PAGE HEADER */}
<section className="border-b border-brand-border/60 pb-6 flex flex-col md:flex-row md:items-end justify-between gap-4">
<div>
<div className="flex items-center gap-3">
<span className="font-mono text-xs text-brand-cyan tracking-widest bg-brand-cyan/10 px-2.5 py-0.5 rounded-full border border-brand-cyan/30 font-medium">
Precision, Not Aggression
</span>
<span className="font-mono text-xs text-slate-400 tracking-wider">
// {homeRegion ? `${homeRegion} Zone` : 'Regional Squadron'}
</span>
</div>
<h1 className="font-headline font-bold text-2xl sm:text-3xl text-white mt-2 tracking-tight">
Club Profile
</h1>
<p className="font-body text-sm text-slate-400 mt-1">
Manage public-facing club identity, branding presentation, and discovery presence.
</p>
</div>
</section>
{/* 4. TOP 4 METRIC CARDS */}
<section className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{/* Card 1: Club Name */}
<div className="relative rounded-2xl glass-card border border-brand-border/60 p-5 sm:p-6 shadow-lg flex flex-col justify-between overflow-hidden">
<div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-brand-cyan/50 via-transparent to-transparent" />
<div className="flex items-center justify-between">
<span className="font-mono text-xs text-slate-400 uppercase tracking-wider font-medium">Club Name</span>
<span className="w-1.5 h-1.5 bg-brand-cyan rounded-full" />
</div>
<div className="mt-3">
<div className="font-headline text-base font-bold text-white truncate">{name || club.name}</div>
<div className="font-mono text-[11px] text-brand-cyan mt-1">3-50 chars valid</div>
</div>
</div>
{/* Card 2: Home Region */}
<div className="relative rounded-2xl glass-card border border-brand-border/60 p-5 sm:p-6 shadow-lg flex flex-col justify-between overflow-hidden">
<div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-brand-cyan/50 via-transparent to-transparent" />
<div className="flex items-center justify-between">
<span className="font-mono text-xs text-slate-400 uppercase tracking-wider font-medium">Home Region</span>
<span className="material-symbols-outlined text-slate-400 text-base">location_on</span>
</div>
<div className="mt-3">
<div className="font-headline text-base font-bold text-white truncate">
{homeRegion || 'Not specified'}
</div>
<div className="font-mono text-[11px] text-slate-400 mt-1">Home Region</div>
</div>
</div>
{/* Card 3: Motorcycle Focus */}
<div className="relative rounded-2xl glass-card border border-brand-border/60 p-5 sm:p-6 shadow-lg flex flex-col justify-between overflow-hidden">
<div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-brand-cyan/50 via-transparent to-transparent" />
<div className="flex items-center justify-between">
<span className="font-mono text-xs text-slate-400 uppercase tracking-wider font-medium">Motorcycle Focus</span>
<span className="material-symbols-outlined text-slate-400 text-base">sports_motorsports</span>
</div>
<div className="mt-3">
<div className="font-headline text-base font-bold text-white truncate">
{motorcycleFocus || 'General'}
</div>
<div className="font-mono text-[11px] text-slate-400 mt-1">Motorcycle Focus</div>
</div>
</div>
{/* Card 4: Discovery Presence */}
<div className="relative rounded-2xl glass-card border border-brand-border/60 p-5 sm:p-6 shadow-lg flex flex-col justify-between overflow-hidden">
<div className="absolute top-0 left-0 right-0 h-0.5 bg-gradient-to-r from-brand-cyan/50 via-transparent to-transparent" />
<div className="flex items-center justify-between">
<span className="font-mono text-xs text-slate-400 uppercase tracking-wider font-medium">Discovery Presence</span>
<span
className={`w-2 h-2 rounded-full ${
club.visibility === 'public' ? 'bg-brand-cyan' : club.visibility === 'unlisted' ? 'bg-amber-400' : 'bg-slate-500'
}`}
/>
</div>
<div className="mt-3">
<div
className={`font-headline text-base font-bold capitalize ${
club.visibility === 'public' ? 'text-brand-cyan' : club.visibility === 'unlisted' ? 'text-amber-400' : 'text-white'
}`}
>
{club.visibility}
</div>
<div className="font-mono text-[11px] text-slate-400 mt-1">
{club.visibility === 'public'
? 'Listed in public club index & directory'
: club.visibility === 'unlisted'
? 'Accessible via direct handle only'
: 'Restricted private club'}
</div>
</div>
</div>
</section>
{/* 5. MAIN WORKSPACE (12-Column Grid) */}
<form onSubmit={handleSave} className="grid grid-cols-1 lg:grid-cols-12 gap-6">
{/* LEFT MAIN (8 cols) */}
<div className="lg:col-span-8 space-y-6">
{/* Status Feedback Banner */}
{saveStatus === 'success' && (
<div className="p-4 rounded bg-secondary/10 border border-secondary/30 flex items-center gap-3 text-secondary">
<span className="material-symbols-outlined text-xl">check_circle</span>
<div className="text-xs font-body font-medium">
Club profile changes have been saved successfully.
</div>
</div>
)}
{saveStatus === 'error' && errorMessage && (
<div className="p-4 rounded bg-error-container border border-error/30 flex items-center gap-3 text-error">
<span className="material-symbols-outlined text-xl">error</span>
<div className="text-xs font-body font-medium">{errorMessage}</div>
</div>
)}
{/* SECTION 1: PUBLIC CLUB IDENTITY */}
<div className="rounded-2xl glass-card border border-brand-border/60 p-5 sm:p-6 space-y-5 shadow-xl">
<div className="flex items-center justify-between border-b border-brand-border/60 pb-3.5">
<div className="flex items-center gap-2">
<span className="material-symbols-outlined text-brand-cyan text-xl">badge</span>
<h2 className="font-headline text-base font-bold text-white">
Section 1: Public Club Identity
</h2>
</div>
</div>
{/* Club Name */}
<div className="space-y-1.5">
<label htmlFor="club-name-input" className="font-mono text-xs text-slate-400 block font-medium">
Club Name
</label>
<div className="relative">
<input
id="club-name-input"
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
disabled={!permissions.canManageSettings || isSaving}
placeholder="e.g. MotorSignal Riders Atlanta"
className="w-full bg-surface-container-low/90 border border-brand-border/80 focus:border-brand-cyan rounded-xl px-3.5 py-2.5 text-sm font-body text-white outline-none transition-colors"
/>
<span
className={`absolute right-3.5 top-3 font-mono text-[11px] font-semibold ${
isNameValid ? 'text-brand-cyan' : 'text-error'
}`}
>
{isNameValid ? 'Valid' : `${trimmedName.length}/50`}
</span>
</div>
<p className="font-body text-xs text-slate-400">
3-50 characters. Displayed on public discovery, ride manifests, and club roster.
</p>
</div>
{/* Club Handle / Identifier (Locked) */}
<div className="space-y-1.5">
<div className="flex items-center justify-between">
<label className="font-mono text-xs text-slate-400 font-medium">
Club Handle / Identifier
</label>
<span className="font-mono text-[10px] px-2 py-0.5 bg-surface-container text-slate-400 border border-brand-border/60 rounded-lg">
Immutable
</span>
</div>
<div className="relative flex items-center">
<span className="material-symbols-outlined absolute left-3.5 text-slate-400 text-base">lock</span>
<input
type="text"
value={`@${club.slug}`}
readOnly
disabled
className="w-full bg-surface-container-lowest/80 border border-brand-border/60 rounded-xl pl-10 pr-3.5 py-2.5 text-xs font-mono text-slate-400 cursor-not-allowed opacity-90"
/>
</div>
<p className="font-body text-xs text-slate-400">
Club handles are permanently reserved and cannot be renamed or reassigned.
</p>
</div>
{/* Club Description */}
<div className="space-y-1.5">
<div className="flex items-center justify-between">
<label htmlFor="club-desc-input" className="font-mono text-xs text-slate-400 block font-medium">
Club Description
</label>
<span className="font-mono text-[11px] text-slate-400">
{description.length}/500
</span>
</div>
<textarea
id="club-desc-input"
rows={3}
value={description}
onChange={(e) => setDescription(e.target.value)}
disabled={!permissions.canManageSettings || isSaving}
placeholder="Describe your club's ethos, riding discipline, and mission..."
className="w-full bg-surface-container-low/90 border border-brand-border/80 focus:border-brand-cyan rounded-xl p-3.5 text-sm font-body text-white outline-none transition-colors leading-relaxed"
/>
<p className="font-body text-xs text-slate-400">
Displayed on your public Club profile.
</p>
</div>
</div>
{/* SECTION 2: REGIONAL & MOTORCYCLE FOCUS */}
<div className="rounded-2xl glass-card border border-brand-border/60 p-5 sm:p-6 space-y-5 shadow-xl">
<div className="flex items-center justify-between border-b border-brand-border/60 pb-3.5">
<div className="flex items-center gap-2">
<span className="material-symbols-outlined text-brand-cyan text-xl">explore</span>
<h2 className="font-headline text-base font-bold text-white">
Section 2: Regional &amp; Motorcycle Focus
</h2>
</div>
<span className="font-mono text-xs text-slate-400">Geo / Discipline</span>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{/* Home Region */}
<div className="space-y-1.5">
<label htmlFor="club-region-input" className="font-mono text-xs text-slate-400 block font-medium">
Home Region
</label>
<input
id="club-region-input"
type="text"
value={homeRegion}
onChange={(e) => setHomeRegion(e.target.value)}
disabled={!permissions.canManageSettings || isSaving}
placeholder="e.g. Atlanta, Georgia"
className="w-full bg-surface-container-low/90 border border-brand-border/80 focus:border-brand-cyan rounded-xl px-3.5 py-2.5 text-sm font-body text-white outline-none transition-colors"
/>
<p className="font-body text-xs text-slate-400">Primary area where your Club is based.</p>
</div>
{/* Motorcycle Focus */}
<div className="space-y-1.5">
<label htmlFor="club-focus-input" className="font-mono text-xs text-slate-400 block font-medium">
Motorcycle Focus
</label>
<input
id="club-focus-input"
type="text"
value={motorcycleFocus}
onChange={(e) => setMotorcycleFocus(e.target.value)}
disabled={!permissions.canManageSettings || isSaving}
placeholder="e.g. Sport / Touring"
className="w-full bg-surface-container-low/90 border border-brand-border/80 focus:border-brand-cyan rounded-xl px-3.5 py-2.5 text-sm font-body text-white outline-none transition-colors"
/>
<p className="font-body text-xs text-slate-400">
Main riding style or motorcycle focus for your Club.
</p>
</div>
</div>
</div>
{/* SECTION 3: LOGO & BANNER */}
<div className="rounded-2xl glass-card border border-brand-border/60 p-5 sm:p-6 space-y-5 shadow-xl">
<div className="flex items-center justify-between border-b border-brand-border/60 pb-3.5">
<div className="flex items-center gap-2">
<span className="material-symbols-outlined text-brand-cyan text-xl">palette</span>
<h2 className="font-headline text-base font-bold text-white">
Section 3: Logo &amp; Banner
</h2>
</div>
<span className="font-mono text-xs text-slate-400">Visual Assets</span>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-5">
{/* Logo Presentation Card */}
<div className="bg-surface-container-low/70 border border-brand-border/60 rounded-xl p-4 flex flex-col justify-between space-y-3">
<div className="flex items-center justify-between font-mono text-xs text-slate-400">
<span>Club Emblem</span>
{logoUrl && (
<button
type="button"
onClick={() => setLogoUrl('')}
disabled={!permissions.canManageSettings || isSaving}
className="text-rose-400 hover:text-rose-300 transition-colors text-[11px] font-mono flex items-center gap-1 cursor-pointer"
>
<span className="material-symbols-outlined text-xs">close</span>
<span>Remove</span>
</button>
)}
</div>
<div className="h-36 bg-surface-container-lowest border border-dashed border-brand-border/80 rounded-xl flex flex-col items-center justify-center relative overflow-hidden">
{logoUrl ? (
<img src={logoUrl} alt="Club logo" className="max-h-24 max-w-24 object-contain rounded-lg" />
) : (
<div className="w-20 h-20 rounded-xl border-2 border-brand-cyan bg-surface-container-high flex flex-col items-center justify-center shadow-lg relative">
<span className="material-symbols-outlined text-brand-cyan text-2xl">two_wheeler</span>
<span className="font-headline text-brand-cyan font-bold text-xs tracking-widest mt-1">
{initials}
</span>
</div>
)}
</div>
<div className="space-y-2 pt-1">
<div className="space-y-1">
<input
type="url"
value={logoUrl}
onChange={(e) => setLogoUrl(e.target.value)}
disabled={!permissions.canManageSettings || isSaving}
placeholder="https://example.com/logo.png"
className={`w-full bg-surface-container-low/90 border ${
!isLogoUrlValid ? 'border-error focus:border-error' : 'border-brand-border/80 focus:border-brand-cyan'
} rounded-xl px-3 py-2 text-xs font-mono text-white outline-none transition-colors`}
/>
{!isLogoUrlValid && (
<p className="font-mono text-[10px] text-error">
Must be a valid HTTPS URL (e.g. https://example.com/logo.png).
</p>
)}
</div>
<p className="font-mono text-[10px] text-slate-400">
Direct file upload requires Cloud Storage integration (planned for future release). Enter an HTTPS image URL or leave blank.
</p>
</div>
</div>
{/* Banner Presentation Card */}
<div className="bg-surface-container-low/70 border border-brand-border/60 rounded-xl p-4 flex flex-col justify-between space-y-3">
<div className="flex items-center justify-between font-mono text-xs text-slate-400">
<span>Banner Presentation</span>
{bannerUrl && (
<button
type="button"
onClick={() => setBannerUrl('')}
disabled={!permissions.canManageSettings || isSaving}
className="text-rose-400 hover:text-rose-300 transition-colors text-[11px] font-mono flex items-center gap-1 cursor-pointer"
>
<span className="material-symbols-outlined text-xs">close</span>
<span>Remove</span>
</button>
)}
</div>
<div className="h-36 bg-surface-container-lowest border border-dashed border-brand-border/80 rounded-xl relative overflow-hidden flex items-center justify-center">
{bannerUrl ? (
<img
src={bannerUrl}
alt="Club banner presentation"
className="w-full h-full object-cover"
/>
) : (
<div className="w-full h-full bg-surface-container-low flex items-center justify-center relative overflow-hidden">
<div className="absolute inset-0 bg-[radial-gradient(#00f2fe_1px,transparent_1px)] [background-size:16px_16px] opacity-10" />
<div className="flex items-center gap-2 font-mono text-xs text-slate-400 z-10">
<span className="material-symbols-outlined text-base text-brand-cyan">image</span>
<span className="tracking-wider font-semibold text-white">{name || club.name}</span>
</div>
</div>
)}
</div>
<div className="space-y-2 pt-1">
<div className="space-y-1">
<input
type="url"
value={bannerUrl}
onChange={(e) => setBannerUrl(e.target.value)}
disabled={!permissions.canManageSettings || isSaving}
placeholder="https://example.com/banner.jpg"
className={`w-full bg-surface-container-low/90 border ${
!isBannerUrlValid ? 'border-error focus:border-error' : 'border-brand-border/80 focus:border-brand-cyan'
} rounded-xl px-3 py-2 text-xs font-mono text-white outline-none transition-colors`}
/>
{!isBannerUrlValid && (
<p className="font-mono text-[10px] text-error">
Must be a valid HTTPS URL (e.g. https://example.com/banner.jpg).
</p>
)}
</div>
<p className="font-mono text-[10px] text-slate-400">
Direct file upload requires Cloud Storage integration (planned for future release). Enter an HTTPS image URL or leave blank.
</p>
</div>
</div>
</div>
</div>
{/* ACTION DOCKED FOOTER */}
<div className="rounded-2xl glass-card border border-brand-border/60 p-5 sm:p-6 flex flex-col sm:flex-row items-center justify-between gap-4 shadow-xl">
<div className="flex items-center gap-2 font-body text-xs text-slate-300">
<span className="material-symbols-outlined text-brand-cyan text-base">check_circle</span>
<span>Saves public club profile information.</span>
</div>
<button
type="submit"
disabled={!canSave || (!isDirty && saveStatus !== 'error')}
className={`w-full sm:w-auto flex items-center justify-center gap-2 px-6 py-2.5 rounded-xl font-headline text-xs font-bold tracking-wider transition-all duration-150 ${
canSave && (isDirty || saveStatus === 'error')
? 'bg-primary-container hover:brightness-110 text-on-primary-container shadow-[0_0_16px_rgba(0,242,254,0.3)] cursor-pointer'
: 'bg-surface-container-high text-slate-500 cursor-not-allowed opacity-60'
}`}
>
{isSaving ? (
<>
<span className="material-symbols-outlined text-base animate-spin">progress_activity</span>
<span>Saving Changes...</span>
</>
) : (
<>
<span className="material-symbols-outlined text-base">check</span>
<span>Save Profile Changes</span>
</>
)}
</button>
</div>
</div>
{/* RIGHT RAIL (4 cols) */}
<div className="lg:col-span-4 space-y-6">
{/* CARD A: PUBLIC DIRECTORY PREVIEW (Live Simulation) */}
<div className="rounded-2xl glass-card border border-brand-border/60 p-5 sm:p-6 space-y-4 shadow-xl">
<div className="flex items-center justify-between border-b border-brand-border/60 pb-3">
<div className="flex items-center gap-2">
<span className="material-symbols-outlined text-brand-cyan text-base">visibility</span>
<span data-section="DIRECTORY PREVIEW" className="font-headline text-sm text-white font-bold">
Directory Preview
</span>
</div>
<span data-badge="LIVE SIMULATION" className="font-mono text-[10px] bg-brand-cyan/10 text-brand-cyan px-2.5 py-0.5 rounded-full border border-brand-cyan/30 font-semibold">
Live Simulation
</span>
</div>
{/* Embedded Public Card Mockup (IDENTITY ONLY, ZERO METRICS) */}
<div className="rounded-xl bg-surface-container-low border border-brand-border/60 overflow-hidden shadow-lg">
{/* Banner Mockup */}
<div className="h-24 bg-surface-container-high relative overflow-hidden">
{bannerUrl ? (
<img
src={bannerUrl}
alt="Directory banner preview"
className="w-full h-full object-cover"
/>
) : (
<div className="w-full h-full bg-surface-container-low flex items-center justify-center relative overflow-hidden">
<div className="absolute inset-0 bg-[radial-gradient(#00f2fe_1px,transparent_1px)] [background-size:16px_16px] opacity-10" />
</div>
)}
<div className="absolute inset-0 bg-gradient-to-b from-transparent to-surface-container-low" />
</div>
<div className="p-4 pt-0 relative">
{/* Emblem overlapping */}
<div className="-mt-8 w-14 h-14 rounded-xl bg-surface-container-high border-2 border-brand-cyan flex flex-col items-center justify-center text-brand-cyan shadow-md overflow-hidden">
{logoUrl ? (
<img src={logoUrl} alt="Emblem preview" className="w-full h-full object-cover" />
) : (
<>
<span className="material-symbols-outlined text-xl">two_wheeler</span>
<span className="font-mono text-[10px] font-bold leading-none">{initials}</span>
</>
)}
</div>
<div className="mt-2 flex items-center">
<h3 className="font-headline text-sm text-white font-bold truncate">
{name || club.name}
</h3>
</div>
<div className="font-mono text-[11px] text-brand-cyan mt-0.5">@{club.slug}</div>
<div className="mt-2 inline-flex items-center gap-1.5 font-mono text-[10px] text-brand-cyan bg-brand-cyan/10 px-2 py-0.5 rounded-full border border-brand-cyan/20">
<span className="material-symbols-outlined text-xs">location_on</span>
<span className="truncate">
{homeRegion || 'Global'} • {motorcycleFocus || 'General'}
</span>
</div>
<p className="mt-3 font-body text-xs text-slate-300 line-clamp-2 leading-relaxed">
{description || 'No club description provided yet.'}
</p>
</div>
</div>
<p className="font-mono text-[10px] text-slate-400 text-center">
Rendered in standard public directory feed (1:1 responsive layout)
</p>
</div>
{/* CARD B: ACCESS & DISCOVERY BOUNDARY */}
<div className="rounded-2xl glass-card border border-brand-border/60 p-5 sm:p-6 space-y-3 shadow-xl">
<div className="flex items-center gap-2 text-white border-b border-brand-border/60 pb-3">
<span className="material-symbols-outlined text-brand-cyan text-base">admin_panel_settings</span>
<h3 className="font-headline text-sm font-bold">Access Controls</h3>
</div>
<p className="font-body text-xs text-slate-300 leading-relaxed">
Access settings (Visibility &amp; Admission Policy) are managed separately under Club Settings.
</p>
<div className="pt-1 flex items-center">
<Link href={`/clubs/${club.slug || club.id}/manage/settings`} className="inline-flex items-center gap-1.5 text-brand-cyan hover:underline font-mono text-xs font-semibold">
<span>Manage Access Settings</span>
<span className="material-symbols-outlined text-sm">arrow_forward</span>
</Link>
</div>
</div>
{/* CARD C: PRIVACY CONTRACT */}
<div className="rounded-2xl glass-card border border-brand-border/60 p-5 sm:p-6 space-y-3 shadow-xl">
<div className="flex items-center gap-2 text-brand-cyan">
<span className="material-symbols-outlined text-base">lock</span>
<span data-section="PRIVACY CONTRACT" className="font-mono text-xs font-bold tracking-wider uppercase">Privacy Contract</span>
</div>
<blockquote className="font-body text-xs italic text-slate-200 border-l-2 border-brand-cyan pl-3 py-1 bg-surface-container-lowest/60 rounded-r leading-relaxed">
&ldquo;Public Club Profile is organizational identity only. Member telemetry, GPS tracks, personal ride logs, and private account data are not included.&rdquo;
</blockquote>
<p className="font-mono text-[10px] text-slate-400">
Telemetry and member activity are strictly isolated.
</p>
</div>
</div>
</form>
</div>
);
}