style: unify marketplace color system across all pages (light + dark)
Apply a consistent design token set across every public page: - Page bg: stone-50 / dark:stone-950 - Cards/surfaces: white / dark:stone-900 (via .card class) - Primary text: stone-900 / dark:stone-100 - Secondary text: stone-600 / dark:stone-400 - Muted/label: stone-500 / dark:stone-500, stone-400 / dark:stone-500 - Accent kicker: amber-700 / dark:amber-400 - Image placeholder: stone-100 / dark:stone-800 - Primary button: stone-900 white / dark:white dark:stone-900 - Amber button: amber-500 white / dark:amber-400 dark:stone-900 - Status available: emerald-100 emerald-700 / dark:emerald-950/50 dark:emerald-400 - Status unavailable: rose-100 rose-700 / dark:rose-950/50 dark:rose-400 Also: remove dead medium-theme CSS overrides from globals.css, add dark:[color-scheme:dark] to date/time inputs so browser native pickers adapt, and unify amber accent to amber-400 in dark. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -23,13 +23,8 @@ function toUtcDateTime(date: string, time: string) {
|
||||
return `${date}T${time || '10:00'}:00.000Z`
|
||||
}
|
||||
|
||||
function inputClassName(hasLeadingIcon = true) {
|
||||
return `w-full border-0 bg-white px-4 py-4 text-sm text-stone-900 outline-none placeholder:text-stone-400 ${hasLeadingIcon ? 'pl-2' : ''}`
|
||||
}
|
||||
|
||||
function selectClassName() {
|
||||
return 'w-full border-0 bg-white py-4 text-sm text-stone-900 outline-none'
|
||||
}
|
||||
const inputBase = 'w-full border-0 bg-white dark:bg-stone-800 px-4 py-4 text-sm text-stone-900 dark:text-stone-100 outline-none placeholder:text-stone-400 dark:placeholder:text-stone-500'
|
||||
const selectBase = 'w-full border-0 bg-white dark:bg-stone-800 py-4 text-sm text-stone-900 dark:text-stone-100 outline-none'
|
||||
|
||||
export default function ExploreSearchForm({
|
||||
pickupLocation,
|
||||
@@ -103,17 +98,17 @@ export default function ExploreSearchForm({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mt-8 rounded-[1.75rem] bg-white p-5 text-stone-900 shadow-[0_24px_80px_rgba(0,0,0,0.16)]">
|
||||
<h2 className="text-3xl font-black tracking-tight">{dict.searchTitle}</h2>
|
||||
<div className="mt-8 rounded-[1.75rem] bg-white dark:bg-stone-900 p-5 text-stone-900 dark:text-stone-100 shadow-[0_24px_80px_rgba(0,0,0,0.16)]">
|
||||
<h2 className="text-3xl font-black tracking-tight text-stone-900 dark:text-stone-100">{dict.searchTitle}</h2>
|
||||
<form onSubmit={handleSubmit} className="mt-5 space-y-4">
|
||||
<div className="grid gap-px overflow-hidden rounded-[1.35rem] border border-stone-200 bg-stone-200 md:grid-cols-2">
|
||||
<label className="flex items-center gap-3 bg-white px-4">
|
||||
<MapPin className="h-5 w-5 text-stone-300" />
|
||||
<div className="grid gap-px overflow-hidden rounded-[1.35rem] border border-stone-200 dark:border-stone-700 bg-stone-200 dark:bg-stone-700 md:grid-cols-2">
|
||||
<label className="flex items-center gap-3 bg-white dark:bg-stone-800 px-4">
|
||||
<MapPin className="h-5 w-5 text-stone-300 dark:text-stone-500" />
|
||||
<select
|
||||
name="pickupLocation"
|
||||
value={filters.pickupLocation}
|
||||
onChange={(event) => updateFilter('pickupLocation', event.target.value)}
|
||||
className={selectClassName()}
|
||||
className={selectBase}
|
||||
>
|
||||
<option value="">{dict.pickupLocation}</option>
|
||||
{cityOptions.map((city) => (
|
||||
@@ -121,13 +116,13 @@ export default function ExploreSearchForm({
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
<label className="flex items-center gap-3 bg-white px-4">
|
||||
<MapPin className="h-5 w-5 text-stone-300" />
|
||||
<label className="flex items-center gap-3 bg-white dark:bg-stone-800 px-4">
|
||||
<MapPin className="h-5 w-5 text-stone-300 dark:text-stone-500" />
|
||||
<select
|
||||
name="dropoffLocation"
|
||||
value={filters.dropoffLocation}
|
||||
onChange={(event) => updateFilter('dropoffLocation', event.target.value)}
|
||||
className={selectClassName()}
|
||||
className={selectBase}
|
||||
>
|
||||
<option value="">{dict.dropoffLocation}</option>
|
||||
{cityOptions.map((city) => (
|
||||
@@ -137,82 +132,82 @@ export default function ExploreSearchForm({
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-px overflow-hidden rounded-[1.35rem] border border-stone-200 bg-stone-200 md:grid-cols-4">
|
||||
<label className="flex items-center gap-3 bg-white px-4">
|
||||
<CalendarDays className="h-5 w-5 text-stone-500" />
|
||||
<div className="grid gap-px overflow-hidden rounded-[1.35rem] border border-stone-200 dark:border-stone-700 bg-stone-200 dark:bg-stone-700 md:grid-cols-4">
|
||||
<label className="flex items-center gap-3 bg-white dark:bg-stone-800 px-4">
|
||||
<CalendarDays className="h-5 w-5 text-stone-500 dark:text-stone-400" />
|
||||
<div className="flex w-full flex-col py-3">
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.14em] text-stone-400">{dict.pickupDate}</span>
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.14em] text-stone-400 dark:text-stone-500">{dict.pickupDate}</span>
|
||||
<input
|
||||
name="pickupDate"
|
||||
type="date"
|
||||
value={filters.pickupDate}
|
||||
min={new Date().toISOString().slice(0, 10)}
|
||||
onChange={(event) => updateFilter('pickupDate', event.target.value)}
|
||||
className="border-0 bg-transparent px-0 py-0 text-sm text-stone-900 outline-none"
|
||||
className="border-0 bg-transparent px-0 py-0 text-sm text-stone-900 dark:text-stone-100 outline-none [color-scheme:light] dark:[color-scheme:dark]"
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
<label className="flex items-center gap-3 bg-white px-4">
|
||||
<Clock3 className="h-5 w-5 text-stone-500" />
|
||||
<label className="flex items-center gap-3 bg-white dark:bg-stone-800 px-4">
|
||||
<Clock3 className="h-5 w-5 text-stone-500 dark:text-stone-400" />
|
||||
<div className="flex w-full flex-col py-3">
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.14em] text-stone-400">{dict.hour}</span>
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.14em] text-stone-400 dark:text-stone-500">{dict.hour}</span>
|
||||
<input
|
||||
name="pickupTime"
|
||||
type="time"
|
||||
value={filters.pickupTime}
|
||||
onChange={(event) => updateFilter('pickupTime', event.target.value)}
|
||||
className="border-0 bg-transparent px-0 py-0 text-sm text-stone-900 outline-none"
|
||||
className="border-0 bg-transparent px-0 py-0 text-sm text-stone-900 dark:text-stone-100 outline-none [color-scheme:light] dark:[color-scheme:dark]"
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
<label className="flex items-center gap-3 bg-white px-4">
|
||||
<CalendarDays className="h-5 w-5 text-stone-500" />
|
||||
<label className="flex items-center gap-3 bg-white dark:bg-stone-800 px-4">
|
||||
<CalendarDays className="h-5 w-5 text-stone-500 dark:text-stone-400" />
|
||||
<div className="flex w-full flex-col py-3">
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.14em] text-stone-400">{dict.returnDate}</span>
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.14em] text-stone-400 dark:text-stone-500">{dict.returnDate}</span>
|
||||
<input
|
||||
name="returnDate"
|
||||
type="date"
|
||||
value={filters.returnDate}
|
||||
min={filters.pickupDate || new Date().toISOString().slice(0, 10)}
|
||||
onChange={(event) => updateFilter('returnDate', event.target.value)}
|
||||
className="border-0 bg-transparent px-0 py-0 text-sm text-stone-900 outline-none"
|
||||
className="border-0 bg-transparent px-0 py-0 text-sm text-stone-900 dark:text-stone-100 outline-none [color-scheme:light] dark:[color-scheme:dark]"
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
<label className="flex items-center gap-3 bg-white px-4">
|
||||
<Clock3 className="h-5 w-5 text-stone-500" />
|
||||
<label className="flex items-center gap-3 bg-white dark:bg-stone-800 px-4">
|
||||
<Clock3 className="h-5 w-5 text-stone-500 dark:text-stone-400" />
|
||||
<div className="flex w-full flex-col py-3">
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.14em] text-stone-400">{dict.hour}</span>
|
||||
<span className="text-xs font-semibold uppercase tracking-[0.14em] text-stone-400 dark:text-stone-500">{dict.hour}</span>
|
||||
<input
|
||||
name="returnTime"
|
||||
type="time"
|
||||
value={filters.returnTime}
|
||||
onChange={(event) => updateFilter('returnTime', event.target.value)}
|
||||
className="border-0 bg-transparent px-0 py-0 text-sm text-stone-900 outline-none"
|
||||
className="border-0 bg-transparent px-0 py-0 text-sm text-stone-900 dark:text-stone-100 outline-none [color-scheme:light] dark:[color-scheme:dark]"
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="relative z-10 grid gap-px overflow-visible rounded-[1.35rem] border border-stone-200 bg-stone-200 lg:grid-cols-[1.1fr_1.1fr_1.35fr]">
|
||||
<label className="flex items-center gap-3 rounded-t-[1.35rem] bg-white px-4 lg:rounded-l-[1.35rem] lg:rounded-tr-none">
|
||||
<TicketPercent className="h-5 w-5 text-stone-300" />
|
||||
<div className="relative z-10 grid gap-px overflow-visible rounded-[1.35rem] border border-stone-200 dark:border-stone-700 bg-stone-200 dark:bg-stone-700 lg:grid-cols-[1.1fr_1.1fr_1.35fr]">
|
||||
<label className="flex items-center gap-3 rounded-t-[1.35rem] bg-white dark:bg-stone-800 px-4 lg:rounded-l-[1.35rem] lg:rounded-tr-none">
|
||||
<TicketPercent className="h-5 w-5 text-stone-300 dark:text-stone-500" />
|
||||
<input
|
||||
name="promoCode"
|
||||
value={filters.promoCode}
|
||||
onChange={(event) => updateFilter('promoCode', event.target.value)}
|
||||
placeholder={dict.promoCode}
|
||||
className={inputClassName()}
|
||||
className={`${inputBase} pl-2`}
|
||||
/>
|
||||
</label>
|
||||
<label className="flex items-center justify-between gap-3 bg-white px-4 py-3">
|
||||
<label className="flex items-center justify-between gap-3 bg-white dark:bg-stone-800 px-4 py-3">
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<span className="text-sm font-semibold text-stone-600">{dict.myAge}</span>
|
||||
<span className="text-sm font-semibold text-stone-600 dark:text-stone-300">{dict.myAge}</span>
|
||||
<select
|
||||
name="driverAge"
|
||||
value={filters.driverAge}
|
||||
onChange={(event) => updateFilter('driverAge', event.target.value)}
|
||||
className="border-0 bg-transparent text-sm font-semibold text-stone-900 outline-none"
|
||||
className="border-0 bg-transparent text-sm font-semibold text-stone-900 dark:text-stone-100 outline-none"
|
||||
>
|
||||
{ageOptions.map((option) => (
|
||||
<option key={option} value={option}>{option}</option>
|
||||
@@ -228,21 +223,21 @@ export default function ExploreSearchForm({
|
||||
type="button"
|
||||
aria-label={dict.ageDescription}
|
||||
onClick={() => setAgeHelpOpen((open) => !open)}
|
||||
className="text-stone-400 transition hover:text-stone-600"
|
||||
className="text-stone-400 dark:text-stone-500 transition hover:text-stone-600 dark:hover:text-stone-300"
|
||||
>
|
||||
<Info className="h-5 w-5" />
|
||||
</button>
|
||||
{ageHelpOpen ? (
|
||||
<div className="absolute bottom-[calc(100%+0.85rem)] right-0 z-30 w-72 rounded-2xl border border-[#ffc400] bg-white px-4 py-3 text-left text-sm leading-6 text-stone-700 shadow-[0_16px_40px_rgba(0,0,0,0.14)]">
|
||||
<div className="absolute bottom-[calc(100%+0.85rem)] right-0 z-30 w-72 rounded-2xl border border-amber-300 dark:border-amber-600 bg-white dark:bg-stone-900 px-4 py-3 text-left text-sm leading-6 text-stone-700 dark:text-stone-200 shadow-[0_16px_40px_rgba(0,0,0,0.14)]">
|
||||
{dict.ageDescription}
|
||||
<span className="absolute right-6 top-full h-3 w-3 -translate-y-1/2 rotate-45 border-b border-r border-[#ffc400] bg-white" />
|
||||
<span className="absolute right-6 top-full h-3 w-3 -translate-y-1/2 rotate-45 border-b border-r border-amber-300 dark:border-amber-600 bg-white dark:bg-stone-900" />
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</label>
|
||||
<button
|
||||
type="submit"
|
||||
className="min-h-[76px] rounded-b-[1.35rem] bg-stone-900 px-6 text-sm font-black uppercase tracking-[0.08em] text-white transition hover:bg-stone-700 lg:rounded-b-none lg:rounded-r-[1.35rem]"
|
||||
className="min-h-[76px] rounded-b-[1.35rem] bg-stone-900 px-6 text-sm font-black uppercase tracking-[0.08em] text-white transition hover:bg-stone-700 dark:bg-amber-400 dark:text-stone-900 dark:hover:bg-amber-300 lg:rounded-b-none lg:rounded-r-[1.35rem]"
|
||||
>
|
||||
{dict.search}
|
||||
</button>
|
||||
|
||||
@@ -59,13 +59,13 @@ export default function ExploreVehicleGrid({ vehicles, dict }: { vehicles: Vehic
|
||||
return (
|
||||
<section>
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-2xl font-bold text-stone-900">{dict.availableVehicles}</h2>
|
||||
<p className="text-sm text-stone-500">{vehicles.length} {dict.listings}</p>
|
||||
<h2 className="text-2xl font-bold text-stone-900 dark:text-stone-100">{dict.availableVehicles}</h2>
|
||||
<p className="text-sm text-stone-500 dark:text-stone-400">{vehicles.length} {dict.listings}</p>
|
||||
</div>
|
||||
<div className="mt-4 grid gap-5 md:grid-cols-2 xl:grid-cols-3">
|
||||
{vehicles.map((vehicle) => (
|
||||
<article key={vehicle.id} className="card overflow-hidden">
|
||||
<div className="aspect-[16/10] bg-stone-100">
|
||||
<div className="aspect-[16/10] bg-stone-100 dark:bg-stone-800">
|
||||
{vehicle.photos[0] ? (
|
||||
// eslint-disable-next-line @next/next/no-img-element
|
||||
<img src={vehicle.photos[0]} alt={`${vehicle.make} ${vehicle.model}`} className="h-full w-full object-cover" />
|
||||
@@ -74,27 +74,27 @@ export default function ExploreVehicleGrid({ vehicles, dict }: { vehicles: Vehic
|
||||
<div className="p-5">
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div>
|
||||
<p className="text-xs uppercase tracking-[0.16em] text-stone-500">{vehicle.company.brand?.displayName ?? dict.rentalCompany}</p>
|
||||
<h3 className="mt-2 text-xl font-bold text-stone-900">{vehicle.make} {vehicle.model}</h3>
|
||||
<p className="mt-1 text-sm text-stone-500">{vehicle.year} · {vehicle.category}</p>
|
||||
<p className="text-xs uppercase tracking-[0.16em] text-stone-500 dark:text-stone-400">{vehicle.company.brand?.displayName ?? dict.rentalCompany}</p>
|
||||
<h3 className="mt-2 text-xl font-bold text-stone-900 dark:text-stone-100">{vehicle.make} {vehicle.model}</h3>
|
||||
<p className="mt-1 text-sm text-stone-500 dark:text-stone-400">{vehicle.year} · {vehicle.category}</p>
|
||||
</div>
|
||||
<span className={`rounded-full px-3 py-1 text-xs font-semibold ${vehicle.availability === false ? 'bg-rose-100 text-rose-700' : 'bg-emerald-100 text-emerald-700'}`}>
|
||||
<span className={`shrink-0 rounded-full px-3 py-1 text-xs font-semibold ${vehicle.availability === false ? 'bg-rose-100 text-rose-700 dark:bg-rose-950/50 dark:text-rose-400' : 'bg-emerald-100 text-emerald-700 dark:bg-emerald-950/50 dark:text-emerald-400'}`}>
|
||||
{getStatusCopy(vehicle, dict)}
|
||||
</span>
|
||||
</div>
|
||||
{vehicle.availability === false && (
|
||||
<p className="mt-3 text-sm text-stone-500">
|
||||
<p className="mt-3 text-sm text-stone-500 dark:text-stone-400">
|
||||
{vehicle.nextAvailableAt ? `${dict.availableFrom} ${formatAvailabilityDate(vehicle.nextAvailableAt)}` : dict.unavailableNoDate}
|
||||
</p>
|
||||
)}
|
||||
<div className="mt-5 flex items-end justify-between">
|
||||
<div>
|
||||
<p className="text-sm text-stone-500">{dict.from}</p>
|
||||
<p className="text-2xl font-black text-stone-900">{formatCents(vehicle.dailyRate)}</p>
|
||||
<p className="text-sm text-stone-500 dark:text-stone-400">{dict.from}</p>
|
||||
<p className="text-2xl font-black text-stone-900 dark:text-stone-100">{formatCents(vehicle.dailyRate)}</p>
|
||||
</div>
|
||||
<Link
|
||||
href={`/explore/${vehicle.company.slug}/vehicles/${vehicle.id}`}
|
||||
className="rounded-full bg-stone-900 px-5 py-2.5 text-sm font-semibold text-white transition hover:bg-stone-700"
|
||||
className="rounded-full bg-stone-900 px-5 py-2.5 text-sm font-semibold text-white transition hover:bg-stone-700 dark:bg-white dark:text-stone-900 dark:hover:bg-stone-100"
|
||||
>
|
||||
{dict.viewVehicle}
|
||||
</Link>
|
||||
@@ -103,7 +103,7 @@ export default function ExploreVehicleGrid({ vehicles, dict }: { vehicles: Vehic
|
||||
</article>
|
||||
))}
|
||||
{vehicles.length === 0 && (
|
||||
<div className="card p-6 text-sm text-stone-500 md:col-span-2 xl:col-span-3">{dict.vehicleUnavailable}</div>
|
||||
<div className="card p-6 text-sm text-stone-500 dark:text-stone-400 md:col-span-2 xl:col-span-3">{dict.vehicleUnavailable}</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -45,7 +45,7 @@ export default async function CompanyProfilePage({ params }: { params: { slug: s
|
||||
unavailable: 'Marketplace indisponible',
|
||||
unavailableTitle: "Les détails de l'entreprise sont temporairement indisponibles.",
|
||||
unavailableBody: "L'API marketplace fonctionne, mais la base de données n'est pas accessible dans cet environnement local.",
|
||||
backToExplore: 'Retour à l’exploration',
|
||||
backToExplore: "Retour à l'exploration",
|
||||
partner: 'Partenaire marketplace',
|
||||
vehicles: 'véhicules',
|
||||
offers: 'offres actives',
|
||||
@@ -82,14 +82,14 @@ export default async function CompanyProfilePage({ params }: { params: { slug: s
|
||||
|
||||
if (!company) {
|
||||
return (
|
||||
<main className="min-h-screen bg-stone-50 py-10">
|
||||
<main className="min-h-screen bg-stone-50 dark:bg-stone-950 py-10">
|
||||
<div className="shell">
|
||||
<section className="card p-8">
|
||||
<p className="text-sm uppercase tracking-[0.18em] text-amber-700">{dict.unavailable}</p>
|
||||
<h1 className="mt-3 text-3xl font-black text-stone-900">{dict.unavailableTitle}</h1>
|
||||
<p className="mt-3 text-stone-600">{dict.unavailableBody}</p>
|
||||
<p className="text-sm uppercase tracking-[0.18em] text-amber-700 dark:text-amber-400">{dict.unavailable}</p>
|
||||
<h1 className="mt-3 text-3xl font-black text-stone-900 dark:text-stone-100">{dict.unavailableTitle}</h1>
|
||||
<p className="mt-3 text-stone-600 dark:text-stone-400">{dict.unavailableBody}</p>
|
||||
<div className="mt-6">
|
||||
<Link href="/explore" className="rounded-full bg-stone-900 px-5 py-2.5 text-sm font-semibold text-white">{dict.backToExplore}</Link>
|
||||
<Link href="/explore" className="rounded-full bg-stone-900 px-5 py-2.5 text-sm font-semibold text-white transition hover:bg-stone-700 dark:bg-white dark:text-stone-900 dark:hover:bg-stone-100">{dict.backToExplore}</Link>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@@ -98,13 +98,13 @@ export default async function CompanyProfilePage({ params }: { params: { slug: s
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-stone-50 py-10">
|
||||
<main className="min-h-screen bg-stone-50 dark:bg-stone-950 py-10">
|
||||
<div className="shell space-y-8">
|
||||
<section className="card p-8">
|
||||
<p className="text-sm uppercase tracking-[0.18em] text-amber-700">{company.brand?.publicCity ?? dict.partner}</p>
|
||||
<h1 className="mt-3 text-4xl font-black text-stone-900">{company.brand?.displayName ?? company.name}</h1>
|
||||
<p className="mt-3 text-stone-600">{company.brand?.publicCountry ?? ''}</p>
|
||||
<div className="mt-6 flex flex-wrap gap-3 text-sm text-stone-500">
|
||||
<p className="text-sm uppercase tracking-[0.18em] text-amber-700 dark:text-amber-400">{company.brand?.publicCity ?? dict.partner}</p>
|
||||
<h1 className="mt-3 text-4xl font-black text-stone-900 dark:text-stone-100">{company.brand?.displayName ?? company.name}</h1>
|
||||
<p className="mt-3 text-stone-600 dark:text-stone-400">{company.brand?.publicCountry ?? ''}</p>
|
||||
<div className="mt-6 flex flex-wrap gap-3 text-sm text-stone-500 dark:text-stone-400">
|
||||
<span>{company.vehicles.length} {dict.vehicles}</span>
|
||||
<span>{company.offers.length} {dict.offers}</span>
|
||||
<span>{dict.rating} {company.brand?.marketplaceRating?.toFixed(1) ?? dict.new}</span>
|
||||
@@ -112,41 +112,41 @@ export default async function CompanyProfilePage({ params }: { params: { slug: s
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold text-stone-900">{dict.currentOffers}</h2>
|
||||
<h2 className="text-2xl font-bold text-stone-900 dark:text-stone-100">{dict.currentOffers}</h2>
|
||||
<div className="mt-4 grid gap-4 md:grid-cols-2">
|
||||
{company.offers.map((offer) => (
|
||||
<div key={offer.id} className="card p-5">
|
||||
<p className="text-sm font-semibold text-stone-900">{offer.title}</p>
|
||||
<p className="mt-2 text-3xl font-black text-amber-700">{offer.discountValue}%</p>
|
||||
<p className="mt-2 text-sm text-stone-500">{dict.validUntil} {new Date(offer.validUntil).toLocaleDateString()}</p>
|
||||
<p className="text-sm font-semibold text-stone-900 dark:text-stone-100">{offer.title}</p>
|
||||
<p className="mt-2 text-3xl font-black text-amber-700 dark:text-amber-400">{offer.discountValue}%</p>
|
||||
<p className="mt-2 text-sm text-stone-500 dark:text-stone-400">{dict.validUntil} {new Date(offer.validUntil).toLocaleDateString()}</p>
|
||||
</div>
|
||||
))}
|
||||
{company.offers.length === 0 && <div className="card p-6 text-sm text-stone-500">{dict.noOffers}</div>}
|
||||
{company.offers.length === 0 && <div className="card p-6 text-sm text-stone-500 dark:text-stone-400">{dict.noOffers}</div>}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold text-stone-900">{dict.fleet}</h2>
|
||||
<h2 className="text-2xl font-bold text-stone-900 dark:text-stone-100">{dict.fleet}</h2>
|
||||
<div className="mt-4 grid gap-5 md:grid-cols-2 xl:grid-cols-3">
|
||||
{company.vehicles.map((vehicle) => (
|
||||
<article key={vehicle.id} className="card overflow-hidden">
|
||||
<div className="aspect-[16/10] bg-stone-100">
|
||||
<div className="aspect-[16/10] bg-stone-100 dark:bg-stone-800">
|
||||
{vehicle.photos[0] ? (
|
||||
// eslint-disable-next-line @next/next/no-img-element
|
||||
<img src={vehicle.photos[0]} alt={`${vehicle.make} ${vehicle.model}`} className="h-full w-full object-cover" />
|
||||
) : null}
|
||||
</div>
|
||||
<div className="p-5">
|
||||
<h3 className="text-xl font-bold text-stone-900">{vehicle.make} {vehicle.model}</h3>
|
||||
<p className="mt-1 text-sm text-stone-500">{vehicle.category}</p>
|
||||
<h3 className="text-xl font-bold text-stone-900 dark:text-stone-100">{vehicle.make} {vehicle.model}</h3>
|
||||
<p className="mt-1 text-sm text-stone-500 dark:text-stone-400">{vehicle.category}</p>
|
||||
{!vehicle.availability && (
|
||||
<p className="mt-2 text-sm text-stone-500">
|
||||
<p className="mt-2 text-sm text-stone-500 dark:text-stone-400">
|
||||
{vehicle.nextAvailableAt ? `${dict.availableFrom} ${new Date(vehicle.nextAvailableAt).toLocaleDateString('en-GB', { year: 'numeric', month: 'long', day: 'numeric' })}` : dict.unavailableNoDate}
|
||||
</p>
|
||||
)}
|
||||
<div className="mt-4 flex items-end justify-between">
|
||||
<p className="text-xl font-black text-stone-900">{formatCurrency(vehicle.dailyRate, 'MAD')}</p>
|
||||
<Link href={`/explore/${params.slug}/vehicles/${vehicle.id}`} className="rounded-full bg-stone-900 px-5 py-2.5 text-sm font-semibold text-white">{dict.viewVehicle}</Link>
|
||||
<p className="text-xl font-black text-stone-900 dark:text-stone-100">{formatCurrency(vehicle.dailyRate, 'MAD')}</p>
|
||||
<Link href={`/explore/${params.slug}/vehicles/${vehicle.id}`} className="rounded-full bg-stone-900 px-5 py-2.5 text-sm font-semibold text-white transition hover:bg-stone-700 dark:bg-white dark:text-stone-900 dark:hover:bg-stone-100">{dict.viewVehicle}</Link>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
@@ -107,15 +107,15 @@ export default async function VehicleDetailPage({ params }: { params: { slug: st
|
||||
|
||||
if (!vehicle) {
|
||||
return (
|
||||
<main className="min-h-screen bg-stone-50 py-10">
|
||||
<main className="min-h-screen bg-stone-50 dark:bg-stone-950 py-10">
|
||||
<div className="shell">
|
||||
<section className="card p-8">
|
||||
<p className="text-sm uppercase tracking-[0.18em] text-amber-700">{dict.unavailable}</p>
|
||||
<p className="text-sm uppercase tracking-[0.18em] text-amber-700 dark:text-amber-400">{dict.unavailable}</p>
|
||||
<h1 className="mt-3 text-3xl font-black text-stone-900 dark:text-stone-100">{dict.unavailableTitle}</h1>
|
||||
<p className="mt-3 text-stone-600 dark:text-stone-400">{dict.unavailableBody}</p>
|
||||
<div className="mt-6 flex gap-3">
|
||||
<Link href={`/explore/${params.slug}`} className="rounded-full bg-stone-900 px-5 py-2.5 text-sm font-semibold text-white">{dict.backToFleet}</Link>
|
||||
<Link href="/explore" className="rounded-full border border-stone-300 px-5 py-2.5 text-sm font-semibold text-stone-700 dark:border-stone-600 dark:text-stone-300">{dict.backToExplore}</Link>
|
||||
<Link href={`/explore/${params.slug}`} className="rounded-full bg-stone-900 px-5 py-2.5 text-sm font-semibold text-white transition hover:bg-stone-700 dark:bg-white dark:text-stone-900 dark:hover:bg-stone-100">{dict.backToFleet}</Link>
|
||||
<Link href="/explore" className="rounded-full border border-stone-200 px-5 py-2.5 text-sm font-semibold text-stone-700 transition hover:border-stone-400 dark:border-stone-700 dark:text-stone-300 dark:hover:border-stone-500">{dict.backToExplore}</Link>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -237,9 +237,9 @@ export default async function ExplorePage({ searchParams }: { searchParams?: Rec
|
||||
).sort((left, right) => left.localeCompare(right))
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-stone-50 py-10">
|
||||
<main className="min-h-screen bg-stone-50 dark:bg-stone-950 py-10">
|
||||
<div className="shell space-y-10">
|
||||
<section className="rounded-[2rem] bg-[linear-gradient(135deg,#1c1917,#57534e)] px-8 py-12 text-white">
|
||||
<section className="rounded-[2rem] bg-[linear-gradient(135deg,#1c1917,#57534e)] dark:bg-[linear-gradient(135deg,#0c0a09,#292524)] px-8 py-12 text-white">
|
||||
<p className="text-sm uppercase tracking-[0.2em] text-amber-300">{dict.kicker}</p>
|
||||
<h1 className="mt-4 text-4xl font-black tracking-tight">{dict.title}</h1>
|
||||
<p className="mt-4 max-w-2xl text-stone-300">{dict.body}</p>
|
||||
@@ -259,29 +259,29 @@ export default async function ExplorePage({ searchParams }: { searchParams?: Rec
|
||||
|
||||
<section>
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-2xl font-bold text-stone-900">{dict.currentDeals}</h2>
|
||||
<p className="text-sm text-stone-500">{dict.featuredOffers}</p>
|
||||
<h2 className="text-2xl font-bold text-stone-900 dark:text-stone-100">{dict.currentDeals}</h2>
|
||||
<p className="text-sm text-stone-500 dark:text-stone-400">{dict.featuredOffers}</p>
|
||||
</div>
|
||||
<div className="mt-4 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
||||
{offers.map((offer) => (
|
||||
<Link key={offer.id} href={`/explore/${offer.company.brand?.subdomain ?? ''}#offers`} className="card p-5 hover:border-amber-300 transition-colors">
|
||||
<p className="text-xs uppercase tracking-[0.18em] text-amber-700">{offer.company.brand?.displayName ?? dict.company}</p>
|
||||
<h3 className="mt-3 text-lg font-semibold text-stone-900">{offer.title}</h3>
|
||||
<p className="mt-3 text-3xl font-black text-stone-900">{offer.discountValue}%</p>
|
||||
<p className="mt-2 text-sm text-stone-500">{dict.validUntil} {new Date(offer.validUntil).toLocaleDateString()}</p>
|
||||
<Link key={offer.id} href={`/explore/${offer.company.brand?.subdomain ?? ''}#offers`} className="card p-5 hover:border-amber-300 dark:hover:border-amber-500 transition-colors">
|
||||
<p className="text-xs uppercase tracking-[0.18em] text-amber-700 dark:text-amber-400">{offer.company.brand?.displayName ?? dict.company}</p>
|
||||
<h3 className="mt-3 text-lg font-semibold text-stone-900 dark:text-stone-100">{offer.title}</h3>
|
||||
<p className="mt-3 text-3xl font-black text-stone-900 dark:text-stone-100">{offer.discountValue}%</p>
|
||||
<p className="mt-2 text-sm text-stone-500 dark:text-stone-400">{dict.validUntil} {new Date(offer.validUntil).toLocaleDateString()}</p>
|
||||
</Link>
|
||||
))}
|
||||
{offers.length === 0 && <div className="card p-6 text-sm text-stone-500 md:col-span-2 xl:col-span-4">{dict.offersUnavailable}</div>}
|
||||
{offers.length === 0 && <div className="card p-6 text-sm text-stone-500 dark:text-stone-400 md:col-span-2 xl:col-span-4">{dict.offersUnavailable}</div>}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<ExploreVehicleGrid vehicles={vehicles} dict={dict} />
|
||||
|
||||
<section>
|
||||
<h2 className="text-2xl font-bold text-stone-900">{dict.browseByCategory}</h2>
|
||||
<h2 className="text-2xl font-bold text-stone-900 dark:text-stone-100">{dict.browseByCategory}</h2>
|
||||
<div className="mt-4 flex flex-wrap gap-3">
|
||||
{dict.categories.map((categoryName, index) => (
|
||||
<Link key={CATEGORY_VALUES[index] ?? categoryName} href={`/explore?category=${CATEGORY_VALUES[index]}`} className="rounded-full border border-stone-300 bg-white px-4 py-2 text-sm font-semibold text-stone-700">
|
||||
<Link key={CATEGORY_VALUES[index] ?? categoryName} href={`/explore?category=${CATEGORY_VALUES[index]}`} className="rounded-full border border-stone-200 bg-white px-4 py-2 text-sm font-semibold text-stone-700 transition hover:border-stone-400 dark:border-stone-700 dark:bg-stone-900 dark:text-stone-300 dark:hover:border-stone-500">
|
||||
{categoryName}
|
||||
</Link>
|
||||
))}
|
||||
@@ -290,17 +290,17 @@ export default async function ExplorePage({ searchParams }: { searchParams?: Rec
|
||||
|
||||
<section>
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-2xl font-bold text-stone-900">{dict.browseByCompany}</h2>
|
||||
<p className="text-sm text-stone-500">{dict.marketplacePartners}</p>
|
||||
<h2 className="text-2xl font-bold text-stone-900 dark:text-stone-100">{dict.browseByCompany}</h2>
|
||||
<p className="text-sm text-stone-500 dark:text-stone-400">{dict.marketplacePartners}</p>
|
||||
</div>
|
||||
<div className="mt-4 grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
||||
{companies.map((company) => (
|
||||
<Link key={company.id} href={`/explore/${company.brand?.subdomain ?? ''}`} className="card p-5 hover:border-amber-300 transition-colors">
|
||||
<p className="text-xs uppercase tracking-[0.18em] text-stone-500">{company.brand?.publicCity ?? dict.marketplacePartner}</p>
|
||||
<h3 className="mt-3 text-lg font-semibold text-stone-900">{company.brand?.displayName ?? dict.rentalCompany}</h3>
|
||||
<p className="mt-2 text-sm text-stone-500">{dict.rating} {company.brand?.marketplaceRating?.toFixed(1) ?? dict.new}</p>
|
||||
<p className="mt-1 text-sm text-stone-500">{company._count.vehicles} {dict.publishedVehicles}</p>
|
||||
<span className="mt-4 inline-flex rounded-full bg-stone-900 px-4 py-2 text-sm font-semibold text-white">{dict.viewFleet}</span>
|
||||
<Link key={company.id} href={`/explore/${company.brand?.subdomain ?? ''}`} className="card p-5 hover:border-amber-300 dark:hover:border-amber-500 transition-colors">
|
||||
<p className="text-xs uppercase tracking-[0.18em] text-stone-500 dark:text-stone-400">{company.brand?.publicCity ?? dict.marketplacePartner}</p>
|
||||
<h3 className="mt-3 text-lg font-semibold text-stone-900 dark:text-stone-100">{company.brand?.displayName ?? dict.rentalCompany}</h3>
|
||||
<p className="mt-2 text-sm text-stone-500 dark:text-stone-400">{dict.rating} {company.brand?.marketplaceRating?.toFixed(1) ?? dict.new}</p>
|
||||
<p className="mt-1 text-sm text-stone-500 dark:text-stone-400">{company._count.vehicles} {dict.publishedVehicles}</p>
|
||||
<span className="mt-4 inline-flex rounded-full bg-stone-900 px-4 py-2 text-sm font-semibold text-white dark:bg-white dark:text-stone-900">{dict.viewFleet}</span>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@ const copy = {
|
||||
en: {
|
||||
kicker: 'Features',
|
||||
title: 'Operations, marketplace discovery, and branded booking.',
|
||||
body: 'RentalDriveGo combines company-only operations with a public marketplace that sends renters to each company’s own payment flow.',
|
||||
body: 'RentalDriveGo combines company-only operations with a public marketplace that sends renters to each company's own payment flow.',
|
||||
cards: [
|
||||
['Private dashboard', 'Fleet, reservations, CRM, team permissions, billing, and reports stay isolated per company.'],
|
||||
['Marketplace discovery', 'Published vehicles and public offers appear on `/explore` for cross-company browsing.'],
|
||||
@@ -19,9 +19,9 @@ const copy = {
|
||||
fr: {
|
||||
kicker: 'Fonctionnalités',
|
||||
title: 'Opérations, découverte marketplace et réservation de marque.',
|
||||
body: 'RentalDriveGo combine des opérations privées pour l’entreprise avec une marketplace publique qui redirige les clients vers le parcours de paiement propre à chaque société.',
|
||||
body: "RentalDriveGo combine des opérations privées pour l'entreprise avec une marketplace publique qui redirige les clients vers le parcours de paiement propre à chaque société.",
|
||||
cards: [
|
||||
['Tableau de bord privé', 'Flotte, réservations, CRM, permissions d’équipe, facturation et rapports restent isolés par entreprise.'],
|
||||
['Tableau de bord privé', "Flotte, réservations, CRM, permissions d'équipe, facturation et rapports restent isolés par entreprise."],
|
||||
['Découverte marketplace', 'Les véhicules publiés et les offres publiques apparaissent sur `/explore` pour une navigation multi-entreprises.'],
|
||||
['Site de réservation de marque', 'Chaque entreprise dispose de son propre sous-domaine où les clients finalisent la réservation et le paiement.'],
|
||||
['Flexibilité de paiement', 'Utilisez AmanPay ou PayPal pour les abonnements et pour les paiements côté entreprise.'],
|
||||
@@ -49,19 +49,19 @@ export default function FeaturesPage() {
|
||||
const dict = copy[language]
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-stone-50">
|
||||
<main className="min-h-screen bg-stone-50 dark:bg-stone-950">
|
||||
<div className="shell space-y-12 py-16">
|
||||
<div className="max-w-3xl">
|
||||
<p className="text-sm font-semibold uppercase tracking-[0.24em] text-amber-700">{dict.kicker}</p>
|
||||
<h1 className="mt-4 text-5xl font-black tracking-tight text-stone-900">{dict.title}</h1>
|
||||
<p className="mt-5 text-lg leading-8 text-stone-600">{dict.body}</p>
|
||||
<p className="text-sm font-semibold uppercase tracking-[0.24em] text-amber-700 dark:text-amber-400">{dict.kicker}</p>
|
||||
<h1 className="mt-4 text-5xl font-black tracking-tight text-stone-900 dark:text-stone-100">{dict.title}</h1>
|
||||
<p className="mt-5 text-lg leading-8 text-stone-600 dark:text-stone-400">{dict.body}</p>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-6 md:grid-cols-2 xl:grid-cols-3">
|
||||
{dict.cards.map(([title, body]) => (
|
||||
<article key={title} className="card p-8">
|
||||
<h2 className="text-xl font-black text-stone-900">{title}</h2>
|
||||
<p className="mt-4 text-sm leading-7 text-stone-600">{body}</p>
|
||||
<h2 className="text-xl font-black text-stone-900 dark:text-stone-100">{title}</h2>
|
||||
<p className="mt-4 text-sm leading-7 text-stone-600 dark:text-stone-400">{body}</p>
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -92,7 +92,7 @@ const copy = {
|
||||
perMonth: '/mois',
|
||||
billedAs: 'Facturé à',
|
||||
getStarted: 'Commencer',
|
||||
footer: 'Toutes les formules incluent un essai gratuit de 14 jours. Aucune carte bancaire n’est requise.',
|
||||
footer: "Toutes les formules incluent un essai gratuit de 14 jours. Aucune carte bancaire n'est requise.",
|
||||
},
|
||||
ar: {
|
||||
monthly: 'شهري',
|
||||
@@ -127,27 +127,27 @@ export default function PricingClient() {
|
||||
const [billing, setBilling] = useState<Billing>('monthly')
|
||||
const dashboardUrl = resolveBrowserAppUrl(process.env.NEXT_PUBLIC_DASHBOARD_URL ?? 'http://localhost:3001/dashboard')
|
||||
|
||||
const savings = annualSavingsPct('STARTER', currency) // same % for all plans
|
||||
const savings = annualSavingsPct('STARTER', currency)
|
||||
|
||||
return (
|
||||
<div className="space-y-10">
|
||||
{/* Toggles */}
|
||||
<div className="flex flex-col items-center gap-6 sm:flex-row sm:justify-center">
|
||||
{/* Billing toggle */}
|
||||
<div className="flex items-center gap-1 rounded-full border border-stone-200 bg-white p-1 shadow-sm">
|
||||
<div className="flex items-center gap-1 rounded-full border border-stone-200 bg-white p-1 shadow-sm dark:border-stone-700 dark:bg-stone-900">
|
||||
{(['monthly', 'annual'] as Billing[]).map((b) => (
|
||||
<button
|
||||
key={b}
|
||||
onClick={() => setBilling(b)}
|
||||
className={`relative rounded-full px-5 py-2 text-sm font-semibold transition-colors ${
|
||||
billing === b
|
||||
? 'bg-stone-900 text-white'
|
||||
: 'text-stone-600 hover:text-stone-900'
|
||||
? 'bg-stone-900 text-white dark:bg-white dark:text-stone-900'
|
||||
: 'text-stone-600 hover:text-stone-900 dark:text-stone-400 dark:hover:text-stone-100'
|
||||
}`}
|
||||
>
|
||||
{b === 'monthly' ? dict.monthly : dict.annual}
|
||||
{b === 'annual' && billing !== 'annual' && (
|
||||
<span className="ml-2 rounded-full bg-amber-100 px-2 py-0.5 text-[10px] font-bold text-amber-700">
|
||||
<span className="ml-2 rounded-full bg-amber-100 px-2 py-0.5 text-[10px] font-bold text-amber-700 dark:bg-amber-950/50 dark:text-amber-400">
|
||||
-{savings}%
|
||||
</span>
|
||||
)}
|
||||
@@ -156,15 +156,15 @@ export default function PricingClient() {
|
||||
</div>
|
||||
|
||||
{/* Currency toggle */}
|
||||
<div className="flex items-center gap-1 rounded-full border border-stone-200 bg-white p-1 shadow-sm">
|
||||
<div className="flex items-center gap-1 rounded-full border border-stone-200 bg-white p-1 shadow-sm dark:border-stone-700 dark:bg-stone-900">
|
||||
{(['MAD', 'USD', 'EUR'] as Currency[]).map((c) => (
|
||||
<button
|
||||
key={c}
|
||||
onClick={() => setCurrency(c)}
|
||||
className={`rounded-full px-4 py-2 text-sm font-semibold transition-colors ${
|
||||
currency === c
|
||||
? 'bg-amber-500 text-white'
|
||||
: 'text-stone-600 hover:text-stone-900'
|
||||
? 'bg-amber-500 text-white dark:bg-amber-400 dark:text-stone-900'
|
||||
: 'text-stone-600 hover:text-stone-900 dark:text-stone-400 dark:hover:text-stone-100'
|
||||
}`}
|
||||
>
|
||||
{c}
|
||||
@@ -174,7 +174,7 @@ export default function PricingClient() {
|
||||
</div>
|
||||
|
||||
{billing === 'annual' && (
|
||||
<p className="text-center text-sm text-amber-700 font-medium">
|
||||
<p className="text-center text-sm font-medium text-amber-700 dark:text-amber-400">
|
||||
{dict.youSave} {savings}% {dict.withAnnual}
|
||||
</p>
|
||||
)}
|
||||
@@ -193,34 +193,34 @@ export default function PricingClient() {
|
||||
key={plan.key}
|
||||
className={`card relative flex flex-col overflow-hidden ${
|
||||
plan.highlight
|
||||
? 'border-amber-400 ring-2 ring-amber-400 ring-offset-2'
|
||||
? 'border-amber-400 ring-2 ring-amber-400 ring-offset-2 dark:ring-offset-stone-950'
|
||||
: ''
|
||||
}`}
|
||||
>
|
||||
{plan.highlight && (
|
||||
<div className="bg-amber-500 py-1.5 text-center text-xs font-bold uppercase tracking-widest text-white">
|
||||
<div className="bg-amber-500 dark:bg-amber-400 py-1.5 text-center text-xs font-bold uppercase tracking-widest text-white dark:text-stone-900">
|
||||
{dict.mostPopular}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-1 flex-col p-8">
|
||||
<p className="text-xs font-bold uppercase tracking-[0.2em] text-amber-700">
|
||||
<p className="text-xs font-bold uppercase tracking-[0.2em] text-amber-700 dark:text-amber-400">
|
||||
{plan.name}
|
||||
</p>
|
||||
<p className="mt-1 text-sm text-stone-500">{plan.tagline}</p>
|
||||
<p className="mt-1 text-sm text-stone-500 dark:text-stone-400">{plan.tagline}</p>
|
||||
|
||||
<div className="mt-6">
|
||||
<div className="flex items-end gap-1">
|
||||
<span className="text-4xl font-black text-stone-900">
|
||||
<span className="text-4xl font-black text-stone-900 dark:text-stone-100">
|
||||
{currency === 'MAD' ? displayPrice : `${sym}${displayPrice}`}
|
||||
</span>
|
||||
{currency === 'MAD' && (
|
||||
<span className="mb-1 text-lg font-semibold text-stone-500">{sym}</span>
|
||||
<span className="mb-1 text-lg font-semibold text-stone-500 dark:text-stone-400">{sym}</span>
|
||||
)}
|
||||
<span className="mb-1 text-sm text-stone-400">{dict.perMonth}</span>
|
||||
<span className="mb-1 text-sm text-stone-400 dark:text-stone-500">{dict.perMonth}</span>
|
||||
</div>
|
||||
{billing === 'annual' && (
|
||||
<p className="mt-1 text-xs text-stone-400">
|
||||
<p className="mt-1 text-xs text-stone-400 dark:text-stone-500">
|
||||
{dict.billedAs}{' '}
|
||||
{currency === 'MAD'
|
||||
? `${price.annual} ${sym}`
|
||||
@@ -232,9 +232,9 @@ export default function PricingClient() {
|
||||
|
||||
<ul className="mt-8 flex-1 space-y-3">
|
||||
{plan.features.map((f) => (
|
||||
<li key={f} className="flex items-start gap-2.5 text-sm text-stone-700">
|
||||
<li key={f} className="flex items-start gap-2.5 text-sm text-stone-700 dark:text-stone-300">
|
||||
<svg
|
||||
className="mt-0.5 h-4 w-4 shrink-0 text-amber-500"
|
||||
className="mt-0.5 h-4 w-4 shrink-0 text-amber-500 dark:text-amber-400"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth={2.5}
|
||||
@@ -251,8 +251,8 @@ export default function PricingClient() {
|
||||
href={`${dashboardUrl}/sign-up?plan=${plan.key}&billing=${billing.toUpperCase()}¤cy=${currency}`}
|
||||
className={`mt-10 block rounded-full px-6 py-3 text-center text-sm font-semibold transition-colors ${
|
||||
plan.highlight
|
||||
? 'bg-amber-500 text-white hover:bg-amber-600'
|
||||
: 'bg-stone-900 text-white hover:bg-stone-700'
|
||||
? 'bg-amber-500 text-white hover:bg-amber-600 dark:bg-amber-400 dark:text-stone-900 dark:hover:bg-amber-300'
|
||||
: 'bg-stone-900 text-white hover:bg-stone-700 dark:bg-white dark:text-stone-900 dark:hover:bg-stone-100'
|
||||
}`}
|
||||
>
|
||||
{dict.getStarted}
|
||||
@@ -264,7 +264,7 @@ export default function PricingClient() {
|
||||
</div>
|
||||
|
||||
{/* Footer note */}
|
||||
<p className="text-center text-sm text-stone-400">{dict.footer}</p>
|
||||
<p className="text-center text-sm text-stone-400 dark:text-stone-500">{dict.footer}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ const copy = {
|
||||
faq: 'Questions fréquentes',
|
||||
items: [
|
||||
['Puis-je changer de formule plus tard ?', 'Oui. Vous pouvez passer à une formule supérieure ou inférieure à tout moment. Les changements prennent effet au cycle de facturation suivant.'],
|
||||
['Qu’est-ce qui compte comme véhicule ?', 'Tout véhicule ajouté à votre tableau de bord de flotte, qu’il soit actif ou non.'],
|
||||
['Y a-t-il des frais d’installation ?', 'Aucun frais d’installation. Vous payez uniquement l’abonnement mensuel ou annuel.'],
|
||||
["Qu'est-ce qui compte comme véhicule ?", "Tout véhicule ajouté à votre tableau de bord de flotte, qu'il soit actif ou non."],
|
||||
["Y a-t-il des frais d'installation ?", "Aucun frais d'installation. Vous payez uniquement l'abonnement mensuel ou annuel."],
|
||||
['Comment fonctionne la visibilité marketplace ?', 'Toutes les formules payantes incluent une présence publique sur RentalDriveGo. Les clients découvrent votre flotte puis sont redirigés vers votre site de réservation.'],
|
||||
],
|
||||
},
|
||||
@@ -47,24 +47,24 @@ export default function PricingPageContent() {
|
||||
const dict = copy[language]
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-[radial-gradient(circle_at_top,#fef3c7,transparent_30%),linear-gradient(180deg,#fafaf9,white)]">
|
||||
<main className="min-h-screen bg-stone-50 dark:bg-stone-950">
|
||||
<div className="shell py-20">
|
||||
<div className="mx-auto max-w-2xl text-center">
|
||||
<p className="text-sm font-semibold uppercase tracking-[0.24em] text-amber-700">{dict.kicker}</p>
|
||||
<h1 className="mt-4 text-5xl font-black tracking-tight text-stone-900">{dict.title}</h1>
|
||||
<p className="mt-5 text-lg leading-8 text-stone-600">{dict.body}</p>
|
||||
<p className="text-sm font-semibold uppercase tracking-[0.24em] text-amber-700 dark:text-amber-400">{dict.kicker}</p>
|
||||
<h1 className="mt-4 text-5xl font-black tracking-tight text-stone-900 dark:text-stone-100">{dict.title}</h1>
|
||||
<p className="mt-5 text-lg leading-8 text-stone-600 dark:text-stone-400">{dict.body}</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-16">
|
||||
<PricingClient />
|
||||
</div>
|
||||
|
||||
<div className="mx-auto mt-24 max-w-3xl divide-y divide-stone-200">
|
||||
<h2 className="pb-8 text-2xl font-bold text-stone-900">{dict.faq}</h2>
|
||||
<div className="mx-auto mt-24 max-w-3xl divide-y divide-stone-200 dark:divide-stone-800">
|
||||
<h2 className="pb-8 text-2xl font-bold text-stone-900 dark:text-stone-100">{dict.faq}</h2>
|
||||
{dict.items.map(([q, a]) => (
|
||||
<div key={q} className="py-6">
|
||||
<p className="font-semibold text-stone-900">{q}</p>
|
||||
<p className="mt-2 text-sm leading-6 text-stone-600">{a}</p>
|
||||
<p className="font-semibold text-stone-900 dark:text-stone-100">{q}</p>
|
||||
<p className="mt-2 text-sm leading-6 text-stone-600 dark:text-stone-400">{a}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@ function StarRating({ value, onChange, label }: { value: number; onChange: (v: n
|
||||
const [hovered, setHovered] = useState(0)
|
||||
return (
|
||||
<div>
|
||||
<p className="text-sm font-medium text-stone-700 mb-1.5">{label}</p>
|
||||
<p className="mb-1.5 text-sm font-medium text-stone-700 dark:text-stone-300">{label}</p>
|
||||
<div className="flex gap-1">
|
||||
{[1, 2, 3, 4, 5].map((n) => (
|
||||
<button
|
||||
@@ -34,7 +34,7 @@ function StarRating({ value, onChange, label }: { value: number; onChange: (v: n
|
||||
className={`h-8 w-8 transition-colors ${
|
||||
n <= (hovered || value)
|
||||
? 'fill-amber-400 text-amber-400'
|
||||
: 'fill-stone-200 text-stone-200'
|
||||
: 'fill-stone-200 text-stone-200 dark:fill-stone-700 dark:text-stone-700'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
@@ -101,18 +101,18 @@ function ReviewPageContent() {
|
||||
|
||||
if (loadState === 'loading') {
|
||||
return (
|
||||
<main className="flex min-h-screen items-center justify-center bg-stone-50 p-6">
|
||||
<p className="text-stone-500 text-sm">Loading…</p>
|
||||
<main className="flex min-h-screen items-center justify-center bg-stone-50 dark:bg-stone-950 p-6">
|
||||
<p className="text-sm text-stone-500 dark:text-stone-400">Loading…</p>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
if (loadState === 'invalid') {
|
||||
return (
|
||||
<main className="flex min-h-screen items-center justify-center bg-stone-50 p-6">
|
||||
<div className="card max-w-md w-full p-8 text-center space-y-3">
|
||||
<p className="text-2xl font-black text-stone-900">Link not found</p>
|
||||
<p className="text-stone-500 text-sm">This review link is invalid or has already been used.</p>
|
||||
<main className="flex min-h-screen items-center justify-center bg-stone-50 dark:bg-stone-950 p-6">
|
||||
<div className="card w-full max-w-md space-y-3 p-8 text-center">
|
||||
<p className="text-2xl font-black text-stone-900 dark:text-stone-100">Link not found</p>
|
||||
<p className="text-sm text-stone-500 dark:text-stone-400">This review link is invalid or has already been used.</p>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
@@ -120,13 +120,13 @@ function ReviewPageContent() {
|
||||
|
||||
if (loadState === 'already_reviewed') {
|
||||
return (
|
||||
<main className="flex min-h-screen items-center justify-center bg-stone-50 p-6">
|
||||
<div className="card max-w-md w-full p-8 text-center space-y-3">
|
||||
<div className="mx-auto flex h-14 w-14 items-center justify-center rounded-full bg-emerald-100">
|
||||
<svg className="h-7 w-7 text-emerald-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}><path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" /></svg>
|
||||
<main className="flex min-h-screen items-center justify-center bg-stone-50 dark:bg-stone-950 p-6">
|
||||
<div className="card w-full max-w-md space-y-3 p-8 text-center">
|
||||
<div className="mx-auto flex h-14 w-14 items-center justify-center rounded-full bg-emerald-100 dark:bg-emerald-950/50">
|
||||
<svg className="h-7 w-7 text-emerald-600 dark:text-emerald-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}><path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" /></svg>
|
||||
</div>
|
||||
<p className="text-xl font-bold text-stone-900">Already reviewed</p>
|
||||
<p className="text-stone-500 text-sm">You have already submitted a review for this rental. Thank you!</p>
|
||||
<p className="text-xl font-bold text-stone-900 dark:text-stone-100">Already reviewed</p>
|
||||
<p className="text-sm text-stone-500 dark:text-stone-400">You have already submitted a review for this rental. Thank you!</p>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
@@ -134,60 +134,60 @@ function ReviewPageContent() {
|
||||
|
||||
if (submitState === 'done') {
|
||||
return (
|
||||
<main className="flex min-h-screen items-center justify-center bg-stone-50 p-6">
|
||||
<div className="card max-w-md w-full p-8 text-center space-y-4">
|
||||
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-emerald-100">
|
||||
<svg className="h-8 w-8 text-emerald-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}><path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" /></svg>
|
||||
<main className="flex min-h-screen items-center justify-center bg-stone-50 dark:bg-stone-950 p-6">
|
||||
<div className="card w-full max-w-md space-y-4 p-8 text-center">
|
||||
<div className="mx-auto flex h-16 w-16 items-center justify-center rounded-full bg-emerald-100 dark:bg-emerald-950/50">
|
||||
<svg className="h-8 w-8 text-emerald-600 dark:text-emerald-400" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeWidth={2}><path strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" /></svg>
|
||||
</div>
|
||||
<h1 className="text-2xl font-black text-stone-900">Thank you!</h1>
|
||||
<p className="text-stone-500">Your review has been submitted and will be visible on {info?.companyName}'s profile.</p>
|
||||
<h1 className="text-2xl font-black text-stone-900 dark:text-stone-100">Thank you!</h1>
|
||||
<p className="text-stone-500 dark:text-stone-400">Your review has been submitted and will be visible on {info?.companyName}'s profile.</p>
|
||||
</div>
|
||||
</main>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="flex min-h-screen items-center justify-center bg-stone-50 p-6">
|
||||
<div className="card max-w-lg w-full overflow-hidden">
|
||||
<main className="flex min-h-screen items-center justify-center bg-stone-50 dark:bg-stone-950 p-6">
|
||||
<div className="card w-full max-w-lg overflow-hidden">
|
||||
{/* Header */}
|
||||
<div className="flex items-center gap-4 border-b border-stone-100 p-6">
|
||||
<div className="flex items-center gap-4 border-b border-stone-200 dark:border-stone-800 p-6">
|
||||
{info?.vehiclePhoto ? (
|
||||
// eslint-disable-next-line @next/next/no-img-element
|
||||
<img src={info.vehiclePhoto} alt={info.vehicle} className="h-16 w-24 rounded-xl object-cover flex-shrink-0" />
|
||||
<img src={info.vehiclePhoto} alt={info.vehicle} className="h-16 w-24 flex-shrink-0 rounded-xl object-cover" />
|
||||
) : (
|
||||
<div className="h-16 w-24 rounded-xl bg-stone-100 flex-shrink-0" />
|
||||
<div className="h-16 w-24 flex-shrink-0 rounded-xl bg-stone-100 dark:bg-stone-800" />
|
||||
)}
|
||||
<div className="min-w-0">
|
||||
<p className="text-xs uppercase tracking-widest text-stone-400 truncate">{info?.companyName}</p>
|
||||
<h1 className="mt-0.5 text-lg font-bold text-stone-900 truncate">{info?.vehicle}</h1>
|
||||
<p className="mt-0.5 text-sm text-stone-500">How was your experience?</p>
|
||||
<p className="truncate text-xs uppercase tracking-widest text-stone-400 dark:text-stone-500">{info?.companyName}</p>
|
||||
<h1 className="mt-0.5 truncate text-lg font-bold text-stone-900 dark:text-stone-100">{info?.vehicle}</h1>
|
||||
<p className="mt-0.5 text-sm text-stone-500 dark:text-stone-400">How was your experience?</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="p-6 space-y-6">
|
||||
<form onSubmit={handleSubmit} className="space-y-6 p-6">
|
||||
<StarRating value={overall} onChange={setOverall} label="Overall experience *" />
|
||||
<StarRating value={vehicle} onChange={setVehicle} label="Vehicle condition (optional)" />
|
||||
<StarRating value={service} onChange={setService} label="Customer service (optional)" />
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-stone-700 mb-1.5">Comments (optional)</label>
|
||||
<label className="mb-1.5 block text-sm font-medium text-stone-700 dark:text-stone-300">Comments (optional)</label>
|
||||
<textarea
|
||||
rows={4}
|
||||
value={comment}
|
||||
onChange={(e) => setComment(e.target.value)}
|
||||
placeholder="Tell us about your rental experience…"
|
||||
className="w-full rounded-xl border border-stone-200 px-4 py-3 text-sm focus:outline-none focus:ring-2 focus:ring-stone-900 resize-none"
|
||||
className="w-full resize-none rounded-xl border border-stone-200 dark:border-stone-700 bg-white dark:bg-stone-900 px-4 py-3 text-sm text-stone-900 dark:text-stone-100 placeholder:text-stone-400 dark:placeholder:text-stone-500 focus:outline-none focus:ring-2 focus:ring-stone-900 dark:focus:ring-stone-400"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{errorMsg && (
|
||||
<p className="rounded-xl bg-rose-50 px-4 py-3 text-sm text-rose-700">{errorMsg}</p>
|
||||
<p className="rounded-xl bg-rose-50 dark:bg-rose-950/40 px-4 py-3 text-sm text-rose-700 dark:text-rose-400">{errorMsg}</p>
|
||||
)}
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
disabled={submitState === 'submitting'}
|
||||
className="w-full rounded-full bg-stone-900 py-3 text-sm font-semibold text-white transition-colors hover:bg-stone-700 disabled:opacity-60"
|
||||
className="w-full rounded-full bg-stone-900 py-3 text-sm font-semibold text-white transition-colors hover:bg-stone-700 disabled:opacity-60 dark:bg-white dark:text-stone-900 dark:hover:bg-stone-100"
|
||||
>
|
||||
{submitState === 'submitting' ? 'Submitting…' : 'Submit review'}
|
||||
</button>
|
||||
@@ -201,8 +201,8 @@ export default function ReviewPage() {
|
||||
return (
|
||||
<Suspense
|
||||
fallback={
|
||||
<main className="flex min-h-screen items-center justify-center bg-stone-50 p-6">
|
||||
<p className="text-stone-500 text-sm">Loading…</p>
|
||||
<main className="flex min-h-screen items-center justify-center bg-stone-50 dark:bg-stone-950 p-6">
|
||||
<p className="text-sm text-stone-500 dark:text-stone-400">Loading…</p>
|
||||
</main>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -14,122 +14,3 @@ body {
|
||||
@apply rounded-2xl border border-stone-200 bg-white shadow-sm transition-colors dark:border-stone-800 dark:bg-stone-900;
|
||||
}
|
||||
|
||||
body[data-theme='medium'] {
|
||||
background-color: rgb(41 37 36);
|
||||
color: rgb(231 229 228);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:bg-stone-950 {
|
||||
background-color: rgb(41 37 36);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:bg-stone-950\/80 {
|
||||
background-color: rgb(41 37 36 / 0.8);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:bg-stone-950\/95 {
|
||||
background-color: rgb(41 37 36 / 0.95);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:bg-stone-950\/50 {
|
||||
background-color: rgb(68 64 60 / 0.5);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:bg-stone-950\/40 {
|
||||
background-color: rgb(68 64 60 / 0.4);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:bg-stone-950\/30 {
|
||||
background-color: rgb(68 64 60 / 0.3);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:bg-stone-900,
|
||||
body[data-theme='medium'] .dark\:bg-stone-900\/80,
|
||||
body[data-theme='medium'] .dark\:bg-stone-900\/70,
|
||||
body[data-theme='medium'] .dark\:bg-stone-900\/60 {
|
||||
background-color: rgb(68 64 60 / 0.85);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:bg-stone-800 {
|
||||
background-color: rgb(87 83 78);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:bg-amber-400 {
|
||||
background-color: rgb(251 191 36);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:border-stone-800 {
|
||||
border-color: rgb(120 113 108);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:border-stone-700,
|
||||
body[data-theme='medium'] .dark\:border-white\/5 {
|
||||
border-color: rgb(87 83 78);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:border-amber-300 {
|
||||
border-color: rgb(252 211 77);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:text-stone-50,
|
||||
body[data-theme='medium'] .dark\:text-stone-100,
|
||||
body[data-theme='medium'] .dark\:text-white {
|
||||
color: rgb(250 250 249);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:text-stone-200 {
|
||||
color: rgb(231 229 228);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:text-stone-300,
|
||||
body[data-theme='medium'] .dark\:text-stone-400 {
|
||||
color: rgb(214 211 209);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:text-stone-500,
|
||||
body[data-theme='medium'] .dark\:text-stone-700,
|
||||
body[data-theme='medium'] .dark\:text-stone-800 {
|
||||
color: rgb(168 162 158);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:text-stone-950 {
|
||||
color: rgb(28 25 23);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:text-slate-100 {
|
||||
color: rgb(250 250 249);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:text-stone-600 {
|
||||
color: rgb(168 162 158);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:text-amber-300 {
|
||||
color: rgb(252 211 77);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:text-sky-400 {
|
||||
color: rgb(125 211 252);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:hover\:bg-stone-800:hover,
|
||||
body[data-theme='medium'] .dark\:hover\:bg-stone-900:hover {
|
||||
background-color: rgb(28 25 23);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:hover\:bg-amber-300:hover {
|
||||
background-color: rgb(252 211 77);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:hover\:text-stone-100:hover,
|
||||
body[data-theme='medium'] .dark\:hover\:text-white:hover {
|
||||
color: rgb(250 250 249);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:hover\:border-stone-200:hover {
|
||||
border-color: rgb(214 211 209);
|
||||
}
|
||||
|
||||
body[data-theme='medium'] .dark\:bg-\[\#111111\] {
|
||||
background-color: rgb(28 25 23);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ const pageMeta = {
|
||||
fr: {
|
||||
kicker: 'Informations du pied de page',
|
||||
cta: 'Besoin de plus de détails ?',
|
||||
support: 'Contactez l’équipe RentalDriveGo via nos canaux officiels pour toute demande commerciale, support ou partenariat.',
|
||||
support: "Contactez l'équipe RentalDriveGo via nos canaux officiels pour toute demande commerciale, support ou partenariat.",
|
||||
},
|
||||
ar: {
|
||||
kicker: 'معلومات التذييل',
|
||||
@@ -28,30 +28,30 @@ export default function FooterContentPage({ slug }: { slug: FooterPageSlug }) {
|
||||
const isArabic = language === 'ar'
|
||||
|
||||
return (
|
||||
<main className="min-h-screen bg-stone-50">
|
||||
<main className="min-h-screen bg-stone-50 dark:bg-stone-950">
|
||||
<div className="mx-auto max-w-4xl px-4 py-16 sm:px-6 lg:px-8">
|
||||
<section className="overflow-hidden rounded-[2rem] border border-stone-200 bg-white shadow-[0_30px_80px_rgba(12,18,28,0.08)]">
|
||||
<div className="bg-[linear-gradient(135deg,#f8fafc,white_45%,#fef3c7)] px-6 py-10 sm:px-10 sm:py-14">
|
||||
<p className="text-sm font-semibold uppercase tracking-[0.24em] text-amber-700">
|
||||
<section className="overflow-hidden rounded-[2rem] border border-stone-200 dark:border-stone-800 bg-white dark:bg-stone-900 shadow-[0_30px_80px_rgba(12,18,28,0.08)]">
|
||||
<div className="bg-stone-50 dark:bg-stone-900 px-6 py-10 sm:px-10 sm:py-14 border-b border-stone-100 dark:border-stone-800">
|
||||
<p className="text-sm font-semibold uppercase tracking-[0.24em] text-amber-700 dark:text-amber-400">
|
||||
{meta.kicker}
|
||||
</p>
|
||||
<h1 className="mt-4 text-4xl font-black tracking-tight text-stone-900 sm:text-5xl">
|
||||
<h1 className="mt-4 text-4xl font-black tracking-tight text-stone-900 dark:text-stone-100 sm:text-5xl">
|
||||
{content.title}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div className={`space-y-6 px-6 py-10 sm:px-10 sm:py-12 ${isArabic ? 'text-right' : 'text-left'}`}>
|
||||
{content.paragraphs.map((paragraph) => (
|
||||
<p key={paragraph} className="text-lg leading-8 text-stone-700">
|
||||
<p key={paragraph} className="text-lg leading-8 text-stone-700 dark:text-stone-300">
|
||||
{paragraph}
|
||||
</p>
|
||||
))}
|
||||
|
||||
<div className="rounded-3xl border border-amber-200 bg-amber-50 px-6 py-5 text-stone-700">
|
||||
<p className="text-sm font-semibold uppercase tracking-[0.18em] text-amber-800">
|
||||
<div className="rounded-3xl border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-950/30 px-6 py-5">
|
||||
<p className="text-sm font-semibold uppercase tracking-[0.18em] text-amber-800 dark:text-amber-400">
|
||||
{meta.cta}
|
||||
</p>
|
||||
<p className="mt-2 text-base leading-7">{meta.support}</p>
|
||||
<p className="mt-2 text-base leading-7 text-stone-700 dark:text-stone-300">{meta.support}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user