@@ -482,7 +483,7 @@ export default function BestTime() {
|
{DAY_LABELS[language][row.day]}
{row.day === today && (
- ·{language === 'en' ? 'today' : 'hoy'}
+ ·{language === 'en' ? 'today' : 'hoy'}
)}
|
diff --git a/src/pages/Compare.jsx b/src/pages/Compare.jsx
index 4f7b0fec..c80a0ab1 100644
--- a/src/pages/Compare.jsx
+++ b/src/pages/Compare.jsx
@@ -63,12 +63,12 @@ function CrossingPanel({ crossing, slug, aggregate, language }) {
{crossing.name}
- {crossing.state}
+ {crossing.state}
-
+
{language === 'en' ? 'Reported standard-passenger wait' : 'Espera reportada, auto estándar'}
@@ -78,7 +78,7 @@ function CrossingPanel({ crossing, slug, aggregate, language }) {
-
+
{language === 'en' ? 'Today’s lightest' : 'Hoy más ligero'}
@@ -88,7 +88,7 @@ function CrossingPanel({ crossing, slug, aggregate, language }) {
-
+
{language === 'en' ? '30-day median' : 'Mediana 30 días'}
@@ -98,7 +98,7 @@ function CrossingPanel({ crossing, slug, aggregate, language }) {
{sampleCount != null && (
-
+
{language === 'en'
? `Based on ${sampleCount} samples`
: `Con base en ${sampleCount} muestras`}
@@ -107,7 +107,7 @@ function CrossingPanel({ crossing, slug, aggregate, language }) {
{language === 'en' ? 'Open full page' : 'Abrir página completa'}
diff --git a/src/pages/CrossingDetail.jsx b/src/pages/CrossingDetail.jsx
index badc8099..db67cc34 100644
--- a/src/pages/CrossingDetail.jsx
+++ b/src/pages/CrossingDetail.jsx
@@ -59,7 +59,7 @@ const TIER_BG = {
sparse: 'rgb(241 245 249)', // slate-100
good: 'rgb(16 185 129)', // emerald-500
typical: 'rgb(245 158 11)', // amber-500
- heavy: 'rgb(244 63 94)', // rose-500
+ heavy: 'rgb(190 18 60)', // rose-700: white chart labels remain legible
};
function formatDistance(km, lang) {
@@ -638,15 +638,15 @@ export default function CrossingDetail() {
aria-selected={isActive}
onClick={() => setSelectedDay(dIdx)}
className={[
- 'h-7 px-2.5 rounded-full text-xs font-medium border transition-colors',
+ 'min-h-11 min-w-11 px-2.5 rounded-full text-xs font-medium border transition-colors',
isActive
- ? 'bg-emerald-600 text-white border-emerald-600'
+ ? 'bg-emerald-700 text-white border-emerald-700'
: 'bg-white dark:bg-gray-900 text-slate-700 dark:text-slate-200 border-slate-200 dark:border-gray-700 hover:bg-slate-50 dark:hover:bg-gray-800',
].join(' ')}
>
{DAY_LABELS[language][dIdx]}
{isToday && (
-
+
{language === 'en' ? '·today' : '·hoy'}
)}
@@ -672,7 +672,7 @@ export default function CrossingDetail() {
// skim — every cell looked alarming regardless of value.
const tier = tierFor(val);
const bg = TIER_BG[tier];
- const textColor = sparse ? 'text-slate-400' : 'text-white';
+ const textColor = sparse ? 'text-slate-600' : tier === 'heavy' ? 'text-white' : 'text-slate-950';
// Ring layering: current hour (sky) wins; otherwise best (emerald).
const ringClass = isCurrent
@@ -699,17 +699,18 @@ export default function CrossingDetail() {
className={`w-full h-10 rounded flex items-center justify-center ${ringClass}`}
style={{ background: bg }}
title={title}
+ role="img"
aria-label={title}
>
-
+
{sparse ? '' : `${val}m`}
{formatHourCompact(h)}
@@ -719,7 +720,7 @@ export default function CrossingDetail() {
})}
-
+
{language === 'en' ? 'Quick (under 30m)' : 'Rápido (menos de 30m)'}
@@ -769,7 +770,7 @@ export default function CrossingDetail() {
{e.source_name}
{e.published_at && (
-
+
{new Date(e.published_at).toLocaleDateString(
language === 'es' ? 'es-MX' : 'en-US',
{ year: 'numeric', month: 'short', day: 'numeric' },
diff --git a/src/pages/Dashboard.jsx b/src/pages/Dashboard.jsx
index 1fa63309..faa64d73 100644
--- a/src/pages/Dashboard.jsx
+++ b/src/pages/Dashboard.jsx
@@ -361,7 +361,7 @@ export default function Dashboard() {
>
{language === 'en' ? 'Border Crossing Intelligence' : 'Inteligencia de Cruces Fronterizos'}
-
+
{language === 'en'
? 'Official CBP wait times to the U.S. · Historical patterns'
: 'Tiempos oficiales de CBP hacia EE.UU. · Patrones históricos'}
@@ -369,7 +369,7 @@ export default function Dashboard() {
{/* Controls row — wraps cleanly on mobile */}
-
+
{language === 'en' ? 'Data fetched: ' : 'Datos consultados: '}
@@ -382,7 +382,7 @@ export default function Dashboard() {
variant={view === 'analytics' ? 'default' : 'outline'}
size="sm"
onClick={() => setView((v) => (v === 'analytics' ? 'live' : 'analytics'))}
- className="gap-1 h-9"
+ className="gap-1 min-h-11"
aria-pressed={view === 'analytics'}
>
@@ -442,7 +442,7 @@ export default function Dashboard() {
-
+
{REGIONS.map((r) => (
-
+
{language === 'en'
? `Showing ${cardCrossings.length} of ${reportingCrossings.length + offlineCrossings.length}`
: `Mostrando ${cardCrossings.length} de ${reportingCrossings.length + offlineCrossings.length}`}
@@ -552,7 +552,7 @@ export default function Dashboard() {
{offlineCrossings.length > 0 && (
setShowWithoutCurrentWaits((value) => !value)}
- className="self-start py-1.5 text-left text-xs text-slate-500 underline decoration-dotted hover:text-slate-900 dark:hover:text-white sm:self-auto sm:text-right"
+ className="self-start min-h-11 py-2 text-left text-xs text-slate-600 underline decoration-dotted hover:text-slate-900 dark:text-slate-300 dark:hover:text-white sm:self-auto sm:text-right"
>
{showWithoutCurrentWaits
? (language === 'en'
@@ -578,7 +578,7 @@ export default function Dashboard() {
<>
-
+
{language === 'en' ? 'Favorites' : 'Favoritos'}
@@ -607,7 +607,7 @@ export default function Dashboard() {
)}
{favCrossings.length > 0 && restCrossings.length > 0 && (
-
+
{language === 'en' ? 'All crossings' : 'Todos los cruces'}
diff --git a/src/pages/Embed.jsx b/src/pages/Embed.jsx
index c55ac992..7204e788 100644
--- a/src/pages/Embed.jsx
+++ b/src/pages/Embed.jsx
@@ -28,6 +28,10 @@ export default function Embed() {
const direction = 'northbound';
const compact = params.get('compact') === 'true';
+ useEffect(() => {
+ document.documentElement.lang = lang;
+ }, [lang]);
+
const [crossings, setCrossings] = useState([]);
const [aggregate, setAggregate] = useState(null);
const [loaded, setLoaded] = useState(false);
@@ -102,20 +106,20 @@ export default function Embed() {
if (!loaded) {
return (
-
+
{lang === 'es' ? 'Cargando…' : 'Loading…'}
-
+
);
}
if (!crossing) {
return (
-
- {lang === 'es' ? 'Cruce no encontrado' : 'Crossing not found'}
+
+ {lang === 'es' ? 'Cruce no encontrado' : 'Crossing not found'}
borderpulse.com
-
+
);
}
@@ -147,9 +151,9 @@ export default function Embed() {
const deltaColor = deltaText
? (deltaText.tone === 'high'
- ? (isDark ? 'text-rose-400' : 'text-rose-600')
+ ? (isDark ? 'text-rose-400' : 'text-rose-700')
: deltaText.tone === 'low'
- ? (isDark ? 'text-emerald-400' : 'text-emerald-600')
+ ? (isDark ? 'text-emerald-400' : 'text-emerald-700')
: subtext)
: '';
@@ -157,14 +161,14 @@ export default function Embed() {
const waitSize = compact ? 'text-3xl' : 'text-4xl';
return (
-
- {crossing.name}
+ {crossing.name}
{FLAG[crossing.state] || ''}
@@ -220,6 +224,6 @@ export default function Embed() {
borderpulse.com →
-
+
);
}
diff --git a/src/pages/Privacy.jsx b/src/pages/Privacy.jsx
index 7bbc0df3..04148a1c 100644
--- a/src/pages/Privacy.jsx
+++ b/src/pages/Privacy.jsx
@@ -1,7 +1,6 @@
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import { ArrowLeft, Database, Megaphone } from 'lucide-react';
-import { Button } from '@/components/ui/button';
import { updatePageMeta, resetPageMeta } from '@/lib/seo';
export default function Privacy({ lang = 'en' }) {
@@ -18,13 +17,11 @@ export default function Privacy({ lang = 'en' }) {
}, [es]);
return (
-
+
-
-
-
- {es ? 'Todos los cruces' : 'All crossings'}
-
+
+
+ {es ? 'Todos los cruces' : 'All crossings'}
);
}
diff --git a/src/pages/WalkOrDrive.jsx b/src/pages/WalkOrDrive.jsx
index a60f903e..cba534e8 100644
--- a/src/pages/WalkOrDrive.jsx
+++ b/src/pages/WalkOrDrive.jsx
@@ -34,7 +34,7 @@ function PanelCard({ icon: Icon, title, wait, sub, lang, recommendedLabel }) {
- {title}
+ {title}
{recommendedLabel && (
@@ -45,7 +45,7 @@ function PanelCard({ icon: Icon, title, wait, sub, lang, recommendedLabel }) {
{wait == null ? '—' : `${wait} min`}
- {sub}
+ {sub}
);
|