UI: Final surgical fix for iPhone XR - 480p Baseline 3.0, CSS filter removal, and structure repair

This commit is contained in:
Avery Felts 2026-01-31 19:54:10 -07:00
parent c3f9a4fc9a
commit 5f87c79b58
3 changed files with 214 additions and 214 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

View File

@ -291,19 +291,19 @@ export function UserHeader({ user, preferences, onModalStateChange }: UserHeader
onLoadedData={() => setIsVideoLoaded(true)}
onPlay={() => setIsVideoPlaying(true)}
className={cn(
"absolute inset-0 w-full h-full object-cover scale-110 brightness-[1.1] dark:brightness-[0.85] transition-all duration-[2000ms] ease-in-out",
"absolute inset-0 w-full h-full object-cover scale-110 transition-opacity duration-[1500ms] ease-in-out",
isVideoPlaying
? "opacity-70 dark:opacity-50 blur-0"
? "opacity-70 dark:opacity-50"
: isVideoLoaded
? "opacity-30 blur-[4px]"
: "opacity-10 blur-sm"
? "opacity-30"
: "opacity-10"
)}
>
<source src="/videos/smoke.mp4" type="video/mp4" />
</video>
{/* Vignette/Readability Overlay */}
<div className="absolute inset-0 bg-gradient-to-b from-black/10 via-transparent to-black/30 dark:from-black/40 dark:via-transparent dark:to-black/50" />
{/* Vignette/Readability Overlay - Reinforced for contrast */}
<div className="absolute inset-0 bg-gradient-to-b from-black/30 via-transparent to-black/50 dark:from-black/60 dark:via-transparent dark:to-black/70 mix-blend-multiply" />
</div>
<div className="container mx-auto px-4 h-16 sm:h-20 flex items-center justify-between relative z-50">
@ -381,226 +381,226 @@ export function UserHeader({ user, preferences, onModalStateChange }: UserHeader
</button>
</div>
</div>
</header>
{/* Side Menu Integration */}
<SideMenu
isOpen={isSideMenuOpen}
onClose={() => setIsSideMenuOpen(false)}
user={user}
userName={userName}
/>
{/* Side Menu Integration */}
<SideMenu
isOpen={isSideMenuOpen}
onClose={() => setIsSideMenuOpen(false)}
user={user}
userName={userName}
/>
{/* Reminder Settings Dialog */}
<Dialog open={showReminderDialog} onOpenChange={setShowReminderDialog}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle className="flex items-center gap-2 font-bold tracking-tight">
<Bell className="h-5 w-5 text-indigo-400" />
Notification Settings
</DialogTitle>
</DialogHeader>
{/* Reminder Settings Dialog */}
<Dialog open={showReminderDialog} onOpenChange={setShowReminderDialog}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle className="flex items-center gap-2 font-bold tracking-tight">
<Bell className="h-5 w-5 text-indigo-400" />
Notification Settings
</DialogTitle>
</DialogHeader>
<div className="space-y-4 py-4 px-1">
{/* Enable/Disable Toggle */}
<div className={cn(
"flex items-center justify-between p-4 rounded-2xl border transition-all",
theme === 'light' ? "bg-slate-50 border-slate-100" : "bg-white/5 border-white/5"
)}>
<div className="flex items-center gap-3">
<div className={cn(
"p-2.5 rounded-xl",
reminderSettings.enabled ? "bg-indigo-500/20 text-indigo-400" : "bg-slate-500/20 text-slate-400"
)}>
{reminderSettings.enabled ? <BellRing className="h-5 w-5" /> : <BellOff className="h-5 w-5" />}
</div>
<div className="flex flex-col">
<span className="text-sm font-bold">
{reminderSettings.enabled ? 'Enabled' : 'Disabled'}
</span>
<span className="text-[10px] opacity-60">
{reminderSettings.enabled ? 'Reminders active' : 'Turn on to get alerts'}
</span>
</div>
<div className="space-y-4 py-4 px-1">
{/* Enable/Disable Toggle */}
<div className={cn(
"flex items-center justify-between p-4 rounded-2xl border transition-all",
theme === 'light' ? "bg-slate-50 border-slate-100" : "bg-white/5 border-white/5"
)}>
<div className="flex items-center gap-3">
<div className={cn(
"p-2.5 rounded-xl",
reminderSettings.enabled ? "bg-indigo-500/20 text-indigo-400" : "bg-slate-500/20 text-slate-400"
)}>
{reminderSettings.enabled ? <BellRing className="h-5 w-5" /> : <BellOff className="h-5 w-5" />}
</div>
<div className="flex flex-col">
<span className="text-sm font-bold">
{reminderSettings.enabled ? 'Enabled' : 'Disabled'}
</span>
<span className="text-[10px] opacity-60">
{reminderSettings.enabled ? 'Reminders active' : 'Turn on to get alerts'}
</span>
</div>
<button
onClick={handleToggleReminders}
disabled={!isSupported || (permission === 'denied' && !reminderSettings.enabled)}
className={cn(
"relative w-12 h-6 rounded-full transition-all duration-300 shadow-inner",
reminderSettings.enabled ? "bg-indigo-500" : "bg-slate-400/30",
(!isSupported || (permission === 'denied' && !reminderSettings.enabled)) && "opacity-50 cursor-not-allowed"
)}
>
<div className={cn(
"absolute top-1 w-4 h-4 rounded-full bg-white shadow-md transition-all duration-300",
reminderSettings.enabled ? "left-7" : "left-1"
)} />
</button>
</div>
<button
onClick={handleToggleReminders}
disabled={!isSupported || (permission === 'denied' && !reminderSettings.enabled)}
className={cn(
"relative w-12 h-6 rounded-full transition-all duration-300 shadow-inner",
reminderSettings.enabled ? "bg-indigo-500" : "bg-slate-400/30",
(!isSupported || (permission === 'denied' && !reminderSettings.enabled)) && "opacity-50 cursor-not-allowed"
)}
>
<div className={cn(
"absolute top-1 w-4 h-4 rounded-full bg-white shadow-md transition-all duration-300",
reminderSettings.enabled ? "left-7" : "left-1"
)} />
</button>
</div>
{/* Frequency Selection */}
{reminderSettings.enabled && (
<div className="space-y-3">
<div className="text-[10px] font-bold uppercase tracking-widest opacity-40 px-1">Reminder Frequency</div>
<div className="grid grid-cols-2 gap-3">
<button
onClick={() => handleFrequencyChange('daily')}
className={cn(
"p-4 rounded-2xl border text-sm font-bold transition-all flex flex-col items-center gap-1",
localFrequency === 'daily'
? 'bg-indigo-500 border-indigo-500 text-white shadow-lg shadow-indigo-500/25 scale-[1.02]'
: 'bg-background border-border hover:border-indigo-500/50'
)}
>
<span>Daily</span>
<span className="text-[10px] font-normal opacity-70">Once a day</span>
</button>
<button
onClick={() => handleFrequencyChange('hourly')}
className={cn(
"p-4 rounded-2xl border text-sm font-bold transition-all flex flex-col items-center gap-1",
localFrequency === 'hourly'
? 'bg-indigo-500 border-indigo-500 text-white shadow-lg shadow-indigo-500/25 scale-[1.02]'
: 'bg-background border-border hover:border-indigo-500/50'
)}
>
<span>Hourly</span>
<span className="text-[10px] font-normal opacity-70">Window alerts</span>
</button>
</div>
</div>
)}
{/* Time Picker (Only for Daily) */}
{reminderSettings.enabled && localFrequency === 'daily' && (
<div className="space-y-3 animate-in fade-in slide-in-from-top-2 duration-300">
<div className="text-[10px] font-bold uppercase tracking-widest opacity-40 px-1">Preferred Time</div>
<div className="flex gap-2 p-1 bg-muted/30 rounded-2xl border border-border/50">
<div className="flex-1">
<Select
value={hourString}
onValueChange={(val) => updateTime(val, minuteString, currentAmpm)}
>
<SelectTrigger className="border-none bg-transparent shadow-none hover:bg-white/5 h-12 rounded-xl">
<SelectValue placeholder="Hour" />
</SelectTrigger>
<SelectContent className="rounded-xl">
{hoursOptions.map((h) => (
<SelectItem key={h} value={h} className="rounded-lg">{h}</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="flex-1">
<Select
value={minuteString}
onValueChange={(val) => updateTime(hourString, val, currentAmpm)}
>
<SelectTrigger className="border-none bg-transparent shadow-none hover:bg-white/5 h-12 rounded-xl">
<SelectValue placeholder="Min" />
</SelectTrigger>
<SelectContent className="rounded-xl">
{minutesOptions.map((m) => (
<SelectItem key={m} value={m} className="rounded-lg">{m}</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="w-24 px-1">
<Select
value={currentAmpm}
onValueChange={(val) => updateTime(hourString, minuteString, val)}
>
<SelectTrigger className="border-none bg-indigo-500/10 text-indigo-400 font-bold shadow-none hover:bg-indigo-500/20 h-10 mt-1 rounded-lg">
<SelectValue placeholder="AM/PM" />
</SelectTrigger>
<SelectContent className="rounded-xl">
<SelectItem value="AM" className="rounded-lg">AM</SelectItem>
<SelectItem value="PM" className="rounded-lg">PM</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</div>
)}
{/* Hourly Alerts Window */}
{reminderSettings.enabled && localFrequency === 'hourly' && (
<div className="space-y-4 animate-in fade-in slide-in-from-top-2 duration-300">
<div className="space-y-2">
<div className="text-[10px] font-bold uppercase tracking-widest opacity-40 px-1">Start Time</div>
<HourlyTimePicker
value={reminderSettings.hourlyStart || '09:00'}
onChange={async (newTime) => {
const [h, m] = newTime.split(':');
const end = (reminderSettings.hourlyEnd || '21:00').split(':');
const newSettings = { ...reminderSettings, hourlyStart: newTime, hourlyEnd: `${end[0]}:${m}` };
setReminderSettings(newSettings);
await saveReminderSettings(newSettings);
}}
/>
</div>
<div className="space-y-2">
<div className="text-[10px] font-bold uppercase tracking-widest opacity-40 px-1">End Time</div>
<HourlyTimePicker
value={reminderSettings.hourlyEnd || '21:00'}
onChange={async (newTime) => {
const [h, m] = newTime.split(':');
const start = (reminderSettings.hourlyStart || '09:00').split(':');
const newSettings = { ...reminderSettings, hourlyEnd: newTime, hourlyStart: `${start[0]}:${m}` };
setReminderSettings(newSettings);
await saveReminderSettings(newSettings);
}}
/>
</div>
<div className="flex items-center gap-2 p-3 bg-indigo-500/5 rounded-2xl border border-indigo-500/10">
<Sparkles className="h-4 w-4 text-indigo-400" />
<p className="text-[10px] text-indigo-400 uppercase font-black tracking-widest">Reminders every 60 minutes</p>
</div>
</div>
)}
{/* Notification Permission Sync */}
{reminderSettings.enabled && isSupported && (
<div className="pt-2">
<Button
onClick={async () => {
const result = await requestPermission();
if (result === 'granted') {
try {
const res = await fetch('/api/notifications/test', { method: 'POST' });
if (res.ok) alert("Success! Push notifications active.");
} catch (err) { console.error(err); }
} else alert("Please enable notifications in settings.");
}}
{/* Frequency Selection */}
{reminderSettings.enabled && (
<div className="space-y-3">
<div className="text-[10px] font-bold uppercase tracking-widest opacity-40 px-1">Reminder Frequency</div>
<div className="grid grid-cols-2 gap-3">
<button
onClick={() => handleFrequencyChange('daily')}
className={cn(
"w-full h-12 rounded-2xl font-bold transition-all shadow-md group",
permission === 'granted'
? 'bg-emerald-500/10 text-emerald-500 hover:bg-emerald-500/20'
: 'bg-emerald-600 text-white hover:bg-emerald-500 hover:scale-[1.02]'
"p-4 rounded-2xl border text-sm font-bold transition-all flex flex-col items-center gap-1",
localFrequency === 'daily'
? 'bg-indigo-500 border-indigo-500 text-white shadow-lg shadow-indigo-500/25 scale-[1.02]'
: 'bg-background border-border hover:border-indigo-500/50'
)}
>
<Bell className="mr-2 h-4 w-4 group-hover:animate-bounce" />
{permission === 'granted' ? 'Permissions Verified' : 'Enable Push Alerts'}
</Button>
<span>Daily</span>
<span className="text-[10px] font-normal opacity-70">Once a day</span>
</button>
<button
onClick={() => handleFrequencyChange('hourly')}
className={cn(
"p-4 rounded-2xl border text-sm font-bold transition-all flex flex-col items-center gap-1",
localFrequency === 'hourly'
? 'bg-indigo-500 border-indigo-500 text-white shadow-lg shadow-indigo-500/25 scale-[1.02]'
: 'bg-background border-border hover:border-indigo-500/50'
)}
>
<span>Hourly</span>
<span className="text-[10px] font-normal opacity-70">Window alerts</span>
</button>
</div>
)}
</div>
)}
{permission === 'denied' && (
<div className="p-4 bg-red-500/10 border border-red-500/20 rounded-2xl">
<p className="text-xs text-red-500 text-center font-medium leading-relaxed">
Browser notifications are currently blocked. To get reminders, please update your site settings.
</p>
{/* Time Picker (Only for Daily) */}
{reminderSettings.enabled && localFrequency === 'daily' && (
<div className="space-y-3 animate-in fade-in slide-in-from-top-2 duration-300">
<div className="text-[10px] font-bold uppercase tracking-widest opacity-40 px-1">Preferred Time</div>
<div className="flex gap-2 p-1 bg-muted/30 rounded-2xl border border-border/50">
<div className="flex-1">
<Select
value={hourString}
onValueChange={(val) => updateTime(val, minuteString, currentAmpm)}
>
<SelectTrigger className="border-none bg-transparent shadow-none hover:bg-white/5 h-12 rounded-xl">
<SelectValue placeholder="Hour" />
</SelectTrigger>
<SelectContent className="rounded-xl">
{hoursOptions.map((h) => (
<SelectItem key={h} value={h} className="rounded-lg">{h}</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="flex-1">
<Select
value={minuteString}
onValueChange={(val) => updateTime(hourString, val, currentAmpm)}
>
<SelectTrigger className="border-none bg-transparent shadow-none hover:bg-white/5 h-12 rounded-xl">
<SelectValue placeholder="Min" />
</SelectTrigger>
<SelectContent className="rounded-xl">
{minutesOptions.map((m) => (
<SelectItem key={m} value={m} className="rounded-lg">{m}</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="w-24 px-1">
<Select
value={currentAmpm}
onValueChange={(val) => updateTime(hourString, minuteString, val)}
>
<SelectTrigger className="border-none bg-indigo-500/10 text-indigo-400 font-bold shadow-none hover:bg-indigo-500/20 h-10 mt-1 rounded-lg">
<SelectValue placeholder="AM/PM" />
</SelectTrigger>
<SelectContent className="rounded-xl">
<SelectItem value="AM" className="rounded-lg">AM</SelectItem>
<SelectItem value="PM" className="rounded-lg">PM</SelectItem>
</SelectContent>
</Select>
</div>
</div>
)}
</div>
</DialogContent>
</Dialog>
</header>
</div>
)}
{/* Hourly Alerts Window */}
{reminderSettings.enabled && localFrequency === 'hourly' && (
<div className="space-y-4 animate-in fade-in slide-in-from-top-2 duration-300">
<div className="space-y-2">
<div className="text-[10px] font-bold uppercase tracking-widest opacity-40 px-1">Start Time</div>
<HourlyTimePicker
value={reminderSettings.hourlyStart || '09:00'}
onChange={async (newTime) => {
const [h, m] = newTime.split(':');
const end = (reminderSettings.hourlyEnd || '21:00').split(':');
const newSettings = { ...reminderSettings, hourlyStart: newTime, hourlyEnd: `${end[0]}:${m}` };
setReminderSettings(newSettings);
await saveReminderSettings(newSettings);
}}
/>
</div>
<div className="space-y-2">
<div className="text-[10px] font-bold uppercase tracking-widest opacity-40 px-1">End Time</div>
<HourlyTimePicker
value={reminderSettings.hourlyEnd || '21:00'}
onChange={async (newTime) => {
const [h, m] = newTime.split(':');
const start = (reminderSettings.hourlyStart || '09:00').split(':');
const newSettings = { ...reminderSettings, hourlyEnd: newTime, hourlyStart: `${start[0]}:${m}` };
setReminderSettings(newSettings);
await saveReminderSettings(newSettings);
}}
/>
</div>
<div className="flex items-center gap-2 p-3 bg-indigo-500/5 rounded-2xl border border-indigo-500/10">
<Sparkles className="h-4 w-4 text-indigo-400" />
<p className="text-[10px] text-indigo-400 uppercase font-black tracking-widest">Reminders every 60 minutes</p>
</div>
</div>
)}
{/* Notification Permission Sync */}
{reminderSettings.enabled && isSupported && (
<div className="pt-2">
<Button
onClick={async () => {
const result = await requestPermission();
if (result === 'granted') {
try {
const res = await fetch('/api/notifications/test', { method: 'POST' });
if (res.ok) alert("Success! Push notifications active.");
} catch (err) { console.error(err); }
} else alert("Please enable notifications in settings.");
}}
className={cn(
"w-full h-12 rounded-2xl font-bold transition-all shadow-md group",
permission === 'granted'
? 'bg-emerald-500/10 text-emerald-500 hover:bg-emerald-500/20'
: 'bg-emerald-600 text-white hover:bg-emerald-500 hover:scale-[1.02]'
)}
>
<Bell className="mr-2 h-4 w-4 group-hover:animate-bounce" />
{permission === 'granted' ? 'Permissions Verified' : 'Enable Push Alerts'}
</Button>
</div>
)}
{permission === 'denied' && (
<div className="p-4 bg-red-500/10 border border-red-500/20 rounded-2xl">
<p className="text-xs text-red-500 text-center font-medium leading-relaxed">
Browser notifications are currently blocked. To get reminders, please update your site settings.
</p>
</div>
)}
</div>
</DialogContent>
</Dialog>
</>
);
}