deploy: reset public forms and white surfaces

This commit is contained in:
DMleadgen 2026-03-27 15:57:59 -06:00
parent e2124cfa66
commit 7160259afd
Signed by: matt
GPG key ID: C2720CF8CD701894
25 changed files with 239 additions and 191 deletions

View file

@ -18,7 +18,7 @@ import { ContactPage } from '@/components/contact-page';
import { AboutPage } from '@/components/about-page';
import { WhoWeServePage } from '@/components/who-we-serve-page';
import { PublicPageHeader, PublicSurface } from '@/components/public-surface';
import { RequestMachineForm } from '@/components/forms/request-machine-form';
import { GetFreeMachineCta } from '@/components/get-free-machine-cta';
// Required for static export - ensures this route is statically generated
export const dynamic = 'force-static';
@ -346,17 +346,23 @@ function renderLocationPage(locationData: any, locationSlug: string) {
</Card>
</div>
{/* CRM Form */}
{/* Placement CTA */}
<PublicSurface>
<CardContent className="p-1">
<div className="text-center mb-6">
<h3 className="text-2xl font-bold mb-2">Get Your Free Vending Machine</h3>
<p className="text-muted-foreground">
Tell us about your location and we'll follow up within one business day.
</p>
<div className="p-1 text-center">
<h3 className="text-2xl font-bold mb-2">Get Your Free Vending Machine</h3>
<p className="text-muted-foreground">
Open the Rocky placement popup and we&apos;ll follow up within one business day with the best next step for your location.
</p>
<div className="mt-6 flex flex-col items-center gap-3">
<GetFreeMachineCta buttonLabel="Open Free Placement Form" />
<a
href={businessConfig.publicCallUrl}
className="inline-flex min-h-11 items-center justify-center rounded-full border border-border bg-white px-4 text-sm font-medium text-foreground transition hover:border-primary/40 hover:text-primary"
>
Call Instead
</a>
</div>
<RequestMachineForm />
</CardContent>
</div>
</PublicSurface>
</section>
@ -404,9 +410,7 @@ function renderLocationPage(locationData: any, locationSlug: string) {
</div>
<div className="text-center">
<Button asChild size="lg" className="rounded-full bg-primary px-6 hover:bg-primary/90">
<Link href="#contact">Get Your Free Machine Today</Link>
</Button>
<GetFreeMachineCta buttonLabel="Get Your Free Machine Today" />
</div>
</section>
</article>

View file

@ -6,6 +6,7 @@ import { businessConfig } from "@/lib/seo-config"
import { MapPin, Phone, ArrowRight, Wrench, Clock } from "lucide-react"
import { Button } from "@/components/ui/button"
import { PublicInset, PublicPageHeader, PublicSurface } from "@/components/public-surface"
import { GetFreeMachineCta } from "@/components/get-free-machine-cta"
export const metadata: Metadata = {
title: "Service Areas | Vending Machines Across Utah | Rocky Mountain Vending",
@ -135,9 +136,7 @@ export default function ServiceAreasPage() {
</a>
<p className="mt-2 text-sm text-muted-foreground">We&apos;ll confirm delivery range, support availability, and the best intake path for your location.</p>
</PublicInset>
<Button asChild className="h-11 rounded-full px-5">
<Link href="/#request-machine">Request a Free Machine</Link>
</Button>
<GetFreeMachineCta buttonLabel="Request a Free Machine" className="h-11 px-5" />
</div>
</PublicSurface>
</div>
@ -247,9 +246,9 @@ export default function ServiceAreasPage() {
</PublicInset>
))}
</div>
<Button asChild className="mt-6 h-11 rounded-full px-5">
<Link href="/#request-machine">Get Your Free Machine</Link>
</Button>
<div className="mt-6">
<GetFreeMachineCta buttonLabel="Get Your Free Machine" className="h-11 px-5" />
</div>
</PublicSurface>
<PublicSurface>

View file

@ -2,10 +2,10 @@ import type { Metadata } from "next";
import Image from "next/image";
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { PageWrapper, PageHeader } from "@/components/page-wrapper";
import { businessConfig } from "@/lib/seo-config";
import { Phone, CheckCircle2, Shield, Clock, MapPin } from "lucide-react";
import Link from "next/link";
import { PublicPageHeader, PublicSurface } from "@/components/public-surface";
export const metadata: Metadata = {
title: "Vending Machine Moving & Relocation Services | Rocky Mountain Vending",
@ -32,10 +32,12 @@ export const metadata: Metadata = {
export default function MovingServicesPage() {
return (
<PageWrapper maxWidth="6xl">
<PageHeader
<div className="container mx-auto max-w-6xl px-4 py-10 md:py-14">
<PublicPageHeader
align="center"
eyebrow="Moving Services"
title="Vending Machine Moving & Relocation Services"
subtitle="Professional Vending Machine Moving in Utah"
description="Professional vending machine moving in Utah for snack, beverage, and combo machines, with careful transport, safer handling, and cleaner scheduling from pickup to placement."
/>
{/* Introduction Section */}
@ -248,7 +250,7 @@ export default function MovingServicesPage() {
{/* Why Choose Us Section */}
<section className="mb-12">
<h2 className="text-3xl font-bold mb-8 tracking-tight text-balance">Why Choose Us for Your Vending Move?</h2>
<Card className="border-secondary/20 bg-secondary/5">
<Card className="border-border/70">
<CardContent className="p-6 md:p-8">
<ul className="space-y-4">
<li className="flex items-start gap-3">
@ -291,29 +293,27 @@ export default function MovingServicesPage() {
{/* CTA Section */}
<section className="mb-12">
<Card className="border-2 shadow-lg [&>div]:!bg-transparent" style={{ background: 'linear-gradient(to right, var(--link-hover-color), var(--link-hover-color-dark))' }}>
<CardContent className="p-10 md:p-12 text-center">
<h2 className="text-2xl md:text-3xl font-bold text-white mb-4 tracking-tight text-balance">
<PublicSurface className="p-10 text-center md:p-12">
<h2 className="text-2xl md:text-3xl font-bold text-foreground mb-4 tracking-tight text-balance">
Ready to Schedule a Hassle-Free Vending Machine Move?
</h2>
<p className="text-white/90 mb-8 max-w-2xl mx-auto text-lg leading-relaxed">
<p className="text-muted-foreground mb-8 max-w-2xl mx-auto text-lg leading-relaxed">
Contact us today for a custom quote based on machine type, pickup/drop-off locations, access challenges,
and any stairs or special requirements involved. We're here to make your relocation simple and stress-free!
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Button asChild size="lg" className="bg-white text-[var(--link-hover-color)] hover:bg-white/90 text-lg h-12 px-8 font-semibold">
<Link href="/#contact">Request a Free Quote</Link>
<Button asChild size="lg" className="text-lg h-12 px-8 font-semibold rounded-full">
<Link href="/contact-us#contact-form">Request a Quote</Link>
</Button>
<Button asChild size="lg" className="bg-secondary text-white hover:bg-secondary/90 text-lg h-12 px-8 font-semibold">
<Button asChild size="lg" variant="outline" className="text-lg h-12 px-8 font-semibold rounded-full">
<a href={businessConfig.phoneUrl} className="flex items-center gap-2">
<Phone className="w-5 h-5" />
{businessConfig.phone}
</a>
</Button>
</div>
</CardContent>
</Card>
</PublicSurface>
</section>
</PageWrapper>
</div>
);
}

View file

@ -7,7 +7,7 @@ import { Card, CardContent } from "@/components/ui/card";
import { ReviewsSection } from "@/components/reviews-section";
import { Button } from "@/components/ui/button";
import Link from "next/link";
import { RequestMachineForm } from "@/components/forms/request-machine-form";
import { GetFreeMachineCta } from "@/components/get-free-machine-cta";
import { PublicInset, PublicPageHeader, PublicSurface } from "@/components/public-surface";
interface LocationPageProps {
@ -346,19 +346,27 @@ export default async function LocationPage({ params }: LocationPageProps) {
</Card>
</div>
{/* CRM Form */}
{/* Placement CTA */}
<PublicSurface className="p-6 md:p-8">
<div className="text-center mb-6">
<h3 className="text-2xl font-bold mb-2">Get Your Free Vending Machine</h3>
<p className="text-muted-foreground">
Tell us about your location and we&apos;ll follow up within one business day to talk through the best machine mix.
Open the free placement popup and we&apos;ll follow up within one business day to talk through the best machine mix for your location.
</p>
</div>
<PublicInset className="mb-5 p-5 text-sm leading-relaxed text-muted-foreground">
Free placement is for qualifying business locations. Share your foot traffic, preferred machine types,
and any site constraints so our team can recommend the right setup.
</PublicInset>
<RequestMachineForm />
<div className="flex flex-col items-center gap-3">
<GetFreeMachineCta buttonLabel="Open Free Placement Form" />
<a
href={businessConfig.publicCallUrl}
className="inline-flex min-h-11 items-center justify-center rounded-full border border-border bg-white px-4 text-sm font-medium text-foreground transition hover:border-primary/40 hover:text-primary"
>
Call Instead
</a>
</div>
</PublicSurface>
</section>
@ -406,9 +414,7 @@ export default async function LocationPage({ params }: LocationPageProps) {
</div>
<div className="text-center">
<Button asChild size="lg" className="bg-primary hover:bg-primary/90">
<Link href="#contact">Get Your Free Machine Today</Link>
</Button>
<GetFreeMachineCta buttonLabel="Get Your Free Machine Today" />
</div>
</section>
</article>

View file

@ -5,7 +5,7 @@ import { getPageBySlug } from '@/lib/wordpress-data-loader'
import { cleanWordPressContent } from '@/lib/clean-wordPress-content'
import type { Metadata } from 'next'
import { PublicPageHeader, PublicSurface } from '@/components/public-surface'
import { RequestMachineForm } from '@/components/forms/request-machine-form'
import { GetFreeMachineCta } from '@/components/get-free-machine-cta'
const WORDPRESS_SLUG = 'vending-machines-for-sale-in-utah'
@ -83,11 +83,20 @@ export default async function MachinesForSalePage() {
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-primary/80">Free Placement</p>
<h2 className="mt-3 text-3xl font-semibold tracking-tight text-balance">Need a free machine instead of buying one?</h2>
<p className="mt-3 text-base leading-relaxed text-muted-foreground">
If you&apos;re a business looking for placement rather than a purchase, use the request form here and we&apos;ll help you sort out the right next step.
If you&apos;re a business looking for placement rather than a purchase, open the free placement popup and we&apos;ll help you sort out the right next step.
</p>
<div className="mt-6">
<GetFreeMachineCta buttonLabel="Open Free Placement Form" />
</div>
</PublicSurface>
<PublicSurface>
<RequestMachineForm />
<PublicSurface className="flex items-center justify-center text-center">
<div className="max-w-xl">
<p className="text-sm font-semibold uppercase tracking-[0.18em] text-primary/80">Need Sales Help?</p>
<h3 className="mt-3 text-2xl font-semibold tracking-tight text-balance">Talk through machine sales, placement, or feature questions.</h3>
<p className="mt-3 text-sm leading-relaxed text-muted-foreground">
We can help with new vs. used options, payment hardware, and whether free placement or a direct purchase makes more sense for your location.
</p>
</div>
</PublicSurface>
</section>
</div>

View file

@ -3,7 +3,7 @@ import { VendingMachinesShowcase } from '@/components/vending-machines-showcase'
import { FeatureCard } from '@/components/feature-card'
import type { Metadata } from 'next'
import { PublicPageHeader, PublicSurface } from '@/components/public-surface'
import { RequestMachineForm } from '@/components/forms/request-machine-form'
import { GetFreeMachineCta } from '@/components/get-free-machine-cta'
export async function generateMetadata(): Promise<Metadata> {
return generateSEOMetadata({
@ -88,10 +88,10 @@ export default async function MachinesWeUsePage() {
<p className="text-xs font-semibold uppercase tracking-[0.2em] text-primary/80">Free Placement</p>
<h2 className="mt-3 text-3xl font-semibold tracking-tight text-balance">Want this kind of setup at your location?</h2>
<p className="mt-3 text-base leading-relaxed text-muted-foreground">
Use the request form here if you want free placement for a qualifying business and we&apos;ll help map out the best machine mix.
If you want free placement for a qualifying business, open the Rocky intake popup and we&apos;ll help map out the best machine mix without dropping the full form into this page.
</p>
<div className="mt-6">
<RequestMachineForm />
<div className="mt-6 flex flex-wrap gap-3">
<GetFreeMachineCta buttonLabel="Open Free Placement Form" />
</div>
</PublicSurface>
</section>

View file

@ -38,8 +38,8 @@ export function ContactPage() {
</PublicSurface>
<aside className="space-y-5">
<Card className="overflow-hidden rounded-[2rem] border-border/70 bg-background shadow-[0_20px_50px_rgba(0,0,0,0.08)]">
<CardContent className="bg-background p-6">
<Card className="overflow-hidden rounded-[2rem] border-border/70 bg-white shadow-[0_20px_50px_rgba(0,0,0,0.08)]">
<CardContent className="bg-white p-6">
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-primary/80">Direct Options</p>
<h2 className="mt-2 text-2xl font-semibold text-foreground">Reach the team directly</h2>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">
@ -47,7 +47,7 @@ export function ContactPage() {
</p>
<div className="mt-6 space-y-4">
<a href={businessConfig.publicCallUrl} className="flex items-start gap-4 rounded-2xl border border-border/60 bg-background px-4 py-4 transition hover:border-primary/35">
<a href={businessConfig.publicCallUrl} className="flex items-start gap-4 rounded-2xl border border-border/60 bg-white px-4 py-4 transition hover:border-primary/35">
<div className="flex h-11 w-11 items-center justify-center rounded-full bg-primary/10 text-primary">
<Phone className="h-5 w-5" />
</div>
@ -58,7 +58,7 @@ export function ContactPage() {
</div>
</a>
<a href={`mailto:${businessConfig.email}?Subject=Rocky%20Mountain%20Vending%20Inquiry`} className="flex items-start gap-4 rounded-2xl border border-border/60 bg-background px-4 py-4 transition hover:border-primary/35">
<a href={`mailto:${businessConfig.email}?Subject=Rocky%20Mountain%20Vending%20Inquiry`} className="flex items-start gap-4 rounded-2xl border border-border/60 bg-white px-4 py-4 transition hover:border-primary/35">
<div className="flex h-11 w-11 items-center justify-center rounded-full bg-primary/10 text-primary">
<Mail className="h-5 w-5" />
</div>

View file

@ -1,65 +1,88 @@
"use client"
import { Phone, MapPin } from "lucide-react"
import { ContactForm } from "@/components/forms/contact-form"
import Link from "next/link"
import { MapPin, Phone, Wrench } from "lucide-react"
import { PublicInset, PublicPageHeader, PublicSurface } from "@/components/public-surface"
import { businessConfig } from "@/lib/seo-config"
export function ContactSection() {
return (
<section id="contact" className="py-20 md:py-28 bg-muted/30">
<div className="container mx-auto px-4">
<PublicPageHeader
className="mb-10 max-w-3xl"
eyebrow="Detailed Questions"
title="Need something more specific? We can sort that out here."
description="If you already handled the quick placement request, use this longer form for service details, sales questions, or anything that needs more context."
eyebrow="Need Something Else?"
title="Repairs, moving, manuals, and sales questions all funnel through one clean contact path."
description="Instead of repeating the full intake form on every page, we keep the detailed service request on the dedicated contact page and use this section as the quick handoff."
/>
<div className="grid gap-12 lg:grid-cols-2 items-start">
<PublicSurface className="space-y-6">
<div className="space-y-6">
<PublicInset className="flex items-start gap-4 p-5">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary/10 text-primary flex-shrink-0">
<Phone className="h-6 w-6" />
</div>
<div>
<div className="font-semibold mb-1 text-foreground">Call or Text Us</div>
<a href={businessConfig.publicCallUrl} className="text-muted-foreground hover:text-foreground transition-colors">
{businessConfig.publicCallNumber}
</a>
<p className="text-xs text-muted-foreground mt-1">Mon-Fri: 8:00 AM - 5:00 PM</p>
<a href={businessConfig.publicSmsUrl} className="text-xs hover:underline mt-2 block">
Or send a text message
</a>
</div>
</PublicInset>
<div className="grid gap-6 lg:grid-cols-[1.05fr_0.95fr] lg:items-start">
<PublicSurface className="p-6 md:p-8">
<p className="text-xs font-semibold uppercase tracking-[0.18em] text-primary/80">Best Next Step</p>
<h2 className="mt-3 text-3xl font-semibold tracking-tight text-balance">
Use the dedicated contact page for service details.
</h2>
<p className="mt-3 text-base leading-relaxed text-muted-foreground">
That page keeps the full Rocky intake for repairs, moving, manuals, machine sales, and anything that
needs more context. It stays off the rest of the site so these pages can stay lighter and more consistent.
</p>
<PublicInset className="flex items-start gap-4 p-5">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary/10 text-primary flex-shrink-0">
<MapPin className="h-6 w-6" />
</div>
<div>
<div className="font-semibold mb-1 text-foreground">Service Areas</div>
<p className="text-muted-foreground">Davis, Salt Lake & Utah Counties</p>
<p className="text-xs text-muted-foreground mt-1">Serving 20+ cities across Utah</p>
</div>
</PublicInset>
<div className="mt-6 flex flex-col gap-3 sm:flex-row">
<Link
href="/contact-us#contact-form"
className="inline-flex min-h-11 items-center justify-center rounded-full bg-primary px-5 text-sm font-medium text-primary-foreground transition hover:bg-primary/90"
>
Open Contact Form
</Link>
<a
href={businessConfig.publicCallUrl}
className="inline-flex min-h-11 items-center justify-center rounded-full border border-border bg-white px-5 text-sm font-medium text-foreground transition hover:border-primary/40 hover:text-primary"
>
Call Instead
</a>
</div>
</PublicSurface>
<PublicSurface className="p-5 md:p-7">
<div className="mb-4">
<h3 className="text-xl font-semibold mb-2">Contact Form</h3>
<p className="text-sm text-muted-foreground">
Tell us more about your needs and we'll get back to you within 24 hours.
</p>
</div>
<div className="min-h-[738px]">
<ContactForm onSubmit={(data) => console.log('Contact form submitted:', data)} />
</div>
</PublicSurface>
<div className="space-y-5">
<PublicInset className="flex items-start gap-4 p-5">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary/10 text-primary shrink-0">
<Phone className="h-6 w-6" />
</div>
<div>
<div className="font-semibold text-foreground">Call or Text Us</div>
<a href={businessConfig.publicCallUrl} className="mt-1 block text-muted-foreground transition hover:text-foreground">
{businessConfig.publicCallNumber}
</a>
<p className="mt-1 text-xs text-muted-foreground">Mon-Fri: 8:00 AM - 5:00 PM</p>
</div>
</PublicInset>
<PublicInset className="flex items-start gap-4 p-5">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary/10 text-primary shrink-0">
<Wrench className="h-6 w-6" />
</div>
<div>
<div className="font-semibold text-foreground">For Repairs or Moving</div>
<p className="mt-1 text-sm leading-relaxed text-muted-foreground">
Include the machine model and a clear text description. You can also text photos or videos to{" "}
<a href={businessConfig.publicSmsUrl} className="font-medium text-foreground underline decoration-primary/35 underline-offset-4 hover:decoration-primary">
{businessConfig.publicSmsNumber}
</a>
.
</p>
</div>
</PublicInset>
<PublicInset className="flex items-start gap-4 p-5">
<div className="flex h-12 w-12 items-center justify-center rounded-full bg-primary/10 text-primary shrink-0">
<MapPin className="h-6 w-6" />
</div>
<div>
<div className="font-semibold text-foreground">Service Areas</div>
<p className="mt-1 text-sm leading-relaxed text-muted-foreground">Davis, Salt Lake, and Utah Counties, plus the surrounding Rocky Mountain Vending service footprint already listed on the site.</p>
</div>
</PublicInset>
</div>
</div>
</div>
</section>

View file

@ -174,7 +174,7 @@ export function ContactForm({ onSubmit, className, defaultIntent = "" }: Contact
<input id="confirm-email" type="email" {...register("confirmEmail")} className="sr-only" tabIndex={-1} />
</div>
<div className="rounded-[1.75rem] border border-border/70 bg-background p-5 shadow-sm md:p-6">
<div className="rounded-[1.75rem] border border-border/70 bg-white p-5 shadow-sm md:p-6">
<PublicSectionHeader
eyebrow="Step 1"
title="How should we reach you?"
@ -233,7 +233,7 @@ export function ContactForm({ onSubmit, className, defaultIntent = "" }: Contact
</div>
</div>
<div className="rounded-[1.75rem] border border-border/70 bg-background p-5 shadow-sm md:p-6">
<div className="rounded-[1.75rem] border border-border/70 bg-white p-5 shadow-sm md:p-6">
<PublicSectionHeader
eyebrow="Step 2"
title="What do you need help with?"
@ -261,7 +261,7 @@ export function ContactForm({ onSubmit, className, defaultIntent = "" }: Contact
/>
</div>
<div className="mt-5 grid gap-3 rounded-2xl border border-border/60 bg-background p-4 text-sm text-muted-foreground md:grid-cols-[auto_1fr]">
<div className="mt-5 grid gap-3 rounded-2xl border border-border/60 bg-white p-4 text-sm text-muted-foreground md:grid-cols-[auto_1fr]">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-primary/10 text-primary">
<Wrench className="h-4 w-4" />
</div>
@ -278,7 +278,7 @@ export function ContactForm({ onSubmit, className, defaultIntent = "" }: Contact
</div>
</div>
<div className="rounded-[1.75rem] border border-border/70 bg-background p-5 shadow-sm md:p-6">
<div className="rounded-[1.75rem] border border-border/70 bg-white p-5 shadow-sm md:p-6">
<PublicSectionHeader
eyebrow="Step 3"
title="Tell us the details"
@ -302,26 +302,23 @@ export function ContactForm({ onSubmit, className, defaultIntent = "" }: Contact
</div>
</div>
<div className="rounded-[1.75rem] border border-border/70 bg-background p-5 shadow-sm md:p-6">
<div className="rounded-[1.75rem] border border-border/70 bg-white p-5 shadow-sm md:p-6">
<PublicSectionHeader
eyebrow="Step 4"
title="Text updates"
description="Required service consent covers scheduling, support, and follow-up texts for this request. Marketing texts stay separate and optional."
description="This single opt-in covers scheduling, support, and follow-up texts for this request."
/>
<div className="mt-5">
<SmsConsentFields
idPrefix="contact"
serviceChecked={Boolean(watchedValues.serviceTextConsent)}
marketingChecked={Boolean(watchedValues.marketingTextConsent)}
onServiceChange={(checked) => setValue("serviceTextConsent", checked, { shouldValidate: true })}
onMarketingChange={(checked) => setValue("marketingTextConsent", checked, { shouldValidate: true })}
serviceError={errors.serviceTextConsent?.message}
marketingError={errors.marketingTextConsent?.message}
/>
</div>
</div>
<div className="rounded-[1.5rem] border border-border/60 bg-background px-4 py-4 text-sm text-muted-foreground">
<div className="rounded-[1.5rem] border border-border/60 bg-white px-4 py-4 text-sm text-muted-foreground">
<div className="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
<div className="space-y-1">
<p className="font-medium text-foreground">Need a faster handoff?</p>
@ -330,14 +327,14 @@ export function ContactForm({ onSubmit, className, defaultIntent = "" }: Contact
<div className="flex flex-wrap gap-2">
<a
href={businessConfig.publicCallUrl}
className="inline-flex items-center gap-2 rounded-full border border-border bg-background px-4 py-2 font-medium text-foreground transition hover:border-primary/40 hover:text-primary"
className="inline-flex items-center gap-2 rounded-full border border-border bg-white px-4 py-2 font-medium text-foreground transition hover:border-primary/40 hover:text-primary"
>
<PhoneCall className="h-4 w-4" />
Call
</a>
<a
href={businessConfig.publicSmsUrl}
className="inline-flex items-center gap-2 rounded-full border border-border bg-background px-4 py-2 font-medium text-foreground transition hover:border-primary/40 hover:text-primary"
className="inline-flex items-center gap-2 rounded-full border border-border bg-white px-4 py-2 font-medium text-foreground transition hover:border-primary/40 hover:text-primary"
>
<MessageSquare className="h-4 w-4" />
Text Photos

View file

@ -16,7 +16,7 @@ const buttonVariants = cva(
destructive:
"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
"border bg-white shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost:
@ -66,4 +66,4 @@ const FormButton = React.forwardRef<HTMLButtonElement, FormButtonProps>(
)
FormButton.displayName = "FormButton"
export { FormButton, buttonVariants }
export { FormButton, buttonVariants }

View file

@ -27,7 +27,7 @@ const FormInput = React.forwardRef<HTMLInputElement, FormInputProps>(
type={type}
data-slot="input"
className={cn(
"h-12 w-full min-w-0 rounded-xl border border-border/70 bg-background/85 px-4 text-base text-foreground shadow-sm transition outline-none",
"h-12 w-full min-w-0 rounded-xl border border-border/70 bg-white px-4 text-base text-foreground shadow-sm transition outline-none",
"placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground",
"focus:border-primary focus:ring-4 focus:ring-primary/15 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
error ? "border-destructive focus:ring-destructive/10" : "",

View file

@ -34,7 +34,7 @@ const FormSelect = React.forwardRef<HTMLSelectElement, FormSelectProps>(
id={selectId}
ref={ref}
className={cn(
"h-12 w-full appearance-none rounded-xl border border-border/70 bg-background/85 px-4 pr-11 text-base text-foreground shadow-sm transition outline-none",
"h-12 w-full appearance-none rounded-xl border border-border/70 bg-white px-4 pr-11 text-base text-foreground shadow-sm transition outline-none",
"focus:border-primary focus:ring-4 focus:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
error ? "border-destructive focus:ring-destructive/10" : "",
className,

View file

@ -26,7 +26,7 @@ const FormTextarea = React.forwardRef<HTMLTextAreaElement, FormTextareaProps>(
id={textareaId}
data-slot="textarea"
className={cn(
"min-h-[136px] w-full rounded-xl border border-border/70 bg-background/85 px-4 py-3 text-base text-foreground shadow-sm transition outline-none",
"min-h-[136px] w-full rounded-xl border border-border/70 bg-white px-4 py-3 text-base text-foreground shadow-sm transition outline-none",
"placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground",
"focus:border-primary focus:ring-4 focus:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
error ? "border-destructive focus:ring-destructive/10" : "",

View file

@ -191,7 +191,7 @@ export function RequestMachineForm({ onSubmit, className }: RequestMachineFormPr
<input id="confirm-email" type="email" {...register("confirmEmail")} className="sr-only" tabIndex={-1} />
</div>
<div className="rounded-[1.75rem] border border-border/70 bg-background p-5 shadow-sm md:p-6">
<div className="rounded-[1.75rem] border border-border/70 bg-white p-5 shadow-sm md:p-6">
<PublicSectionHeader
eyebrow="Step 1"
title="Business contact"
@ -274,21 +274,21 @@ export function RequestMachineForm({ onSubmit, className }: RequestMachineFormPr
</div>
</div>
<div className="rounded-[1.75rem] border border-border/70 bg-background p-5 shadow-sm md:p-6">
<div className="rounded-[1.75rem] border border-border/70 bg-white p-5 shadow-sm md:p-6">
<PublicSectionHeader
eyebrow="Step 2"
title="What should we plan for?"
description="Tell us what kind of setup you'd like so we can recommend the right mix."
/>
<div className="mt-5 grid gap-3 rounded-[1.5rem] border border-border/60 bg-background p-4 md:grid-cols-2">
<div className="mt-5 grid gap-3 rounded-[1.5rem] border border-border/60 bg-white p-4 md:grid-cols-2">
{MACHINE_TYPE_OPTIONS.map((option) => {
const isChecked = selectedMachineTypes.includes(option.value)
return (
<label
key={option.value}
htmlFor={`machine-type-${option.value}`}
className="flex cursor-pointer items-start gap-3 rounded-xl border border-border/60 bg-background px-4 py-3 transition hover:border-primary/35"
className="flex cursor-pointer items-start gap-3 rounded-xl border border-border/60 bg-white px-4 py-3 transition hover:border-primary/35"
>
<Checkbox
id={`machine-type-${option.value}`}
@ -320,7 +320,7 @@ export function RequestMachineForm({ onSubmit, className }: RequestMachineFormPr
},
})}
/>
<div className="rounded-2xl border border-border/60 bg-background p-4 text-sm text-muted-foreground">
<div className="rounded-2xl border border-border/60 bg-white p-4 text-sm text-muted-foreground">
<div className="flex items-center gap-2 font-medium text-foreground">
<ClipboardCheck className="h-4 w-4 text-primary" />
Free placement intake
@ -332,7 +332,7 @@ export function RequestMachineForm({ onSubmit, className }: RequestMachineFormPr
</div>
</div>
<div className="rounded-[1.75rem] border border-border/70 bg-background p-5 shadow-sm md:p-6">
<div className="rounded-[1.75rem] border border-border/70 bg-white p-5 shadow-sm md:p-6">
<PublicSectionHeader
eyebrow="Step 3"
title="Anything else we should know?"
@ -349,21 +349,18 @@ export function RequestMachineForm({ onSubmit, className }: RequestMachineFormPr
</div>
</div>
<div className="rounded-[1.75rem] border border-border/70 bg-background p-5 shadow-sm md:p-6">
<div className="rounded-[1.75rem] border border-border/70 bg-white p-5 shadow-sm md:p-6">
<PublicSectionHeader
eyebrow="Step 4"
title="Text updates"
description="Required service consent covers scheduling, installation planning, service, and follow-up texts for this request. Marketing texts stay separate and optional."
description="This single opt-in covers scheduling, installation planning, service, and follow-up texts for this request."
/>
<div className="mt-5">
<SmsConsentFields
idPrefix="request-machine"
serviceChecked={Boolean(watchedValues.serviceTextConsent)}
marketingChecked={Boolean(watchedValues.marketingTextConsent)}
onServiceChange={(checked) => setValue("serviceTextConsent", checked, { shouldValidate: true })}
onMarketingChange={(checked) => setValue("marketingTextConsent", checked, { shouldValidate: true })}
serviceError={errors.serviceTextConsent?.message}
marketingError={errors.marketingTextConsent?.message}
/>
</div>
</div>
@ -383,7 +380,7 @@ export function RequestMachineForm({ onSubmit, className }: RequestMachineFormPr
</FormButton>
<a
href={businessConfig.publicCallUrl}
className="inline-flex min-h-11 items-center justify-center gap-2 rounded-full border border-border bg-background px-4 text-sm font-medium text-foreground transition hover:border-primary/40 hover:text-primary"
className="inline-flex min-h-11 items-center justify-center gap-2 rounded-full border border-border bg-white px-4 text-sm font-medium text-foreground transition hover:border-primary/40 hover:text-primary"
>
<PhoneCall className="h-4 w-4" />
Call

View file

@ -32,10 +32,10 @@ function PolicyLinks() {
type SmsConsentFieldsProps = {
idPrefix: string
marketingChecked: boolean
marketingChecked?: boolean
marketingError?: string
mode?: "chat" | "forms"
onMarketingChange: (checked: boolean) => void
onMarketingChange?: (checked: boolean) => void
onServiceChange: (checked: boolean) => void
serviceChecked: boolean
serviceError?: string
@ -43,17 +43,17 @@ type SmsConsentFieldsProps = {
export function SmsConsentFields({
idPrefix,
marketingChecked,
marketingError,
marketingChecked: _marketingChecked,
marketingError: _marketingError,
mode = "forms",
onMarketingChange,
onMarketingChange: _onMarketingChange,
onServiceChange,
serviceChecked,
serviceError,
}: SmsConsentFieldsProps) {
return (
<div className="space-y-3">
<div className="flex items-start gap-3 rounded-2xl border border-border/60 bg-background/90 px-4 py-3">
<div className="flex items-start gap-3 rounded-2xl border border-border/60 bg-white px-4 py-3">
<Checkbox
id={`${idPrefix}-service-consent`}
checked={serviceChecked}
@ -64,36 +64,13 @@ export function SmsConsentFields({
htmlFor={`${idPrefix}-service-consent`}
className="text-xs leading-relaxed text-muted-foreground"
>
I agree to receive conversational SMS from {businessConfig.legalName} about my inquiry, scheduling,
support, repairs, moving, and follow-up. Message frequency varies. Message and data rates may apply.
Reply STOP to opt out and HELP for help. Consent is not a condition of purchase.
I agree to Terms & Conditions provided by {businessConfig.legalName}. By providing my phone number, I agree
to receive text messages about my inquiry, scheduling, support, repairs, moving, and follow-up. Message
frequency varies. Message and data rates may apply. Reply STOP to opt out and HELP for help.
<PolicyLinks />
</Label>
</div>
{serviceError ? <p className="text-xs text-destructive">{serviceError}</p> : null}
{mode === "forms" ? (
<>
<div className="flex items-start gap-3 rounded-2xl border border-border/60 bg-background/90 px-4 py-3">
<Checkbox
id={`${idPrefix}-marketing-consent`}
checked={marketingChecked}
onCheckedChange={(checked) => onMarketingChange(Boolean(checked))}
className="mt-0.5"
/>
<Label
htmlFor={`${idPrefix}-marketing-consent`}
className="text-xs leading-relaxed text-muted-foreground"
>
I agree to receive promotional and marketing SMS from {businessConfig.legalName}. Message frequency
varies. Message and data rates may apply. Reply STOP to opt out and HELP for help. Consent is not a
condition of purchase.
<PolicyLinks />
</Label>
</div>
{marketingError ? <p className="text-xs text-destructive">{marketingError}</p> : null}
</>
) : null}
</div>
)
}

View file

@ -0,0 +1,37 @@
"use client"
import { useState } from "react"
import { Button } from "@/components/ui/button"
import { GetFreeMachineModal } from "@/components/get-free-machine-modal"
import { cn } from "@/lib/utils"
type GetFreeMachineCtaProps = {
buttonLabel?: string
className?: string
size?: "default" | "sm" | "lg"
variant?: "default" | "outline" | "secondary" | "ghost" | "link" | "brand"
}
export function GetFreeMachineCta({
buttonLabel = "Get Free Machine",
className,
size = "lg",
variant = "default",
}: GetFreeMachineCtaProps) {
const [isOpen, setIsOpen] = useState(false)
return (
<>
<Button
type="button"
size={size}
variant={variant}
className={cn("rounded-full px-6", className)}
onClick={() => setIsOpen(true)}
>
{buttonLabel}
</Button>
<GetFreeMachineModal open={isOpen} onOpenChange={setIsOpen} />
</>
)
}

View file

@ -565,7 +565,7 @@ export function ManualsPageClient({
placeholder="Search manuals by name, manufacturer, or category..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="h-12 rounded-xl border-border/70 bg-background/85 pl-10 shadow-sm"
className="h-12 rounded-xl border-border/70 bg-white pl-10 shadow-sm"
/>
</div>
@ -588,7 +588,7 @@ export function ManualsPageClient({
}
}}
>
<SelectTrigger className="w-full rounded-xl border-border/70 bg-background/85 shadow-sm sm:w-[200px]">
<SelectTrigger className="w-full rounded-xl border-border/70 bg-white shadow-sm sm:w-[200px]">
<SelectValue placeholder="All Manufacturers" />
</SelectTrigger>
<SelectContent>
@ -614,7 +614,7 @@ export function ManualsPageClient({
}}
disabled={!selectedManufacturer && filteredCategories.length === categories.length}
>
<SelectTrigger className="w-full rounded-xl border-border/70 bg-background/85 shadow-sm sm:w-[200px]">
<SelectTrigger className="w-full rounded-xl border-border/70 bg-white shadow-sm sm:w-[200px]">
<SelectValue placeholder="All Categories" />
</SelectTrigger>
<SelectContent>
@ -665,7 +665,7 @@ export function ManualsPageClient({
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between gap-3 sm:gap-4">
<div className="flex items-center gap-3 w-full sm:w-auto">
<span className="text-sm text-muted-foreground flex-shrink-0">View:</span>
<div className="inline-flex flex-1 items-center rounded-full border border-border/70 bg-background/90 p-1 shadow-sm sm:flex-initial">
<div className="inline-flex flex-1 items-center rounded-full border border-border/70 bg-white p-1 shadow-sm sm:flex-initial">
<Button
variant="ghost"
size="sm"

View file

@ -54,7 +54,7 @@ export function PublicSurface({
return (
<Component
className={cn(
"rounded-[2rem] border border-border/70 bg-background p-5 shadow-[0_24px_60px_rgba(15,23,42,0.08)] md:p-7",
"rounded-[2rem] border border-border/70 bg-white p-5 shadow-[0_20px_48px_rgba(15,23,42,0.08)] md:p-7",
className,
)}
{...props}
@ -72,7 +72,7 @@ export function PublicInset({
return (
<div
className={cn(
"rounded-[1.5rem] border border-border/60 bg-background p-4 shadow-sm",
"rounded-[1.5rem] border border-border/60 bg-white p-4 shadow-sm",
className,
)}
{...props}

View file

@ -11,7 +11,7 @@ export function RequestMachineSection() {
<section id="request-machine" className="bg-background py-16 md:py-24">
<div className="container mx-auto px-4">
<div className="grid gap-8 lg:grid-cols-[minmax(0,0.9fr)_minmax(0,1.1fr)] lg:items-start">
<PublicSurface className="bg-background p-6 md:p-8 lg:sticky lg:top-28">
<PublicSurface className="bg-white p-6 md:p-8 lg:sticky lg:top-28">
<div className="inline-flex items-center gap-2 rounded-full bg-primary/10 px-3 py-1 text-xs font-semibold uppercase tracking-[0.16em] text-primary">
<Package className="h-4 w-4" />
Free Placement
@ -33,7 +33,7 @@ export function RequestMachineSection() {
</PublicInset>
<div className="mt-6 flex flex-wrap gap-3">
<a href={businessConfig.publicCallUrl} className="inline-flex min-h-11 items-center justify-center rounded-full border border-border bg-background px-4 text-sm font-medium text-foreground transition hover:border-primary/40 hover:text-primary">
<a href={businessConfig.publicCallUrl} className="inline-flex min-h-11 items-center justify-center rounded-full border border-border bg-white px-4 text-sm font-medium text-foreground transition hover:border-primary/40 hover:text-primary">
Call Instead
</a>
<Link href="/contact-us#contact-form" className="inline-flex min-h-11 items-center gap-2 rounded-full text-sm font-medium text-foreground transition hover:text-primary">
@ -43,7 +43,7 @@ export function RequestMachineSection() {
</div>
</PublicSurface>
<PublicSurface className="bg-background p-5 md:p-7">
<PublicSurface className="bg-white p-5 md:p-7">
<RequestMachineForm onSubmit={(data) => console.log("Machine request form submitted:", data)} />
</PublicSurface>
</div>

View file

@ -141,11 +141,11 @@ export function ReviewsPage() {
</p>
</div>
<div className="mt-6 grid gap-4 sm:grid-cols-2">
<Link href="/#request-machine" className="rounded-[1.5rem] border border-border/60 bg-background/90 p-5 text-left transition hover:border-primary/30 hover:text-primary">
<Link href="/#request-machine" className="rounded-[1.5rem] border border-border/60 bg-white p-5 text-left transition hover:border-primary/30 hover:text-primary">
<h3 className="text-lg font-semibold text-foreground">Free Placement</h3>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">Start a request for free vending machine placement at your business.</p>
</Link>
<Link href="/contact-us#contact-form" className="rounded-[1.5rem] border border-border/60 bg-background/90 p-5 text-left transition hover:border-primary/30 hover:text-primary">
<Link href="/contact-us#contact-form" className="rounded-[1.5rem] border border-border/60 bg-white p-5 text-left transition hover:border-primary/30 hover:text-primary">
<h3 className="text-lg font-semibold text-foreground">Service or Sales</h3>
<p className="mt-2 text-sm leading-relaxed text-muted-foreground">Reach out about repairs, moving, manuals, parts, or machine sales.</p>
</Link>

View file

@ -398,7 +398,7 @@ export function SiteChatWidget() {
{isOpen ? (
<div
data-testid="site-chat-panel"
className="pointer-events-auto flex w-[min(24rem,calc(100vw-1.5rem))] flex-col overflow-hidden rounded-[1.75rem] border border-border/70 bg-background/95 shadow-[0_24px_80px_rgba(0,0,0,0.2)] backdrop-blur-xl"
className="pointer-events-auto flex w-[min(24rem,calc(100vw-1.5rem))] flex-col overflow-hidden rounded-[1.75rem] border border-border/70 bg-white shadow-[0_24px_80px_rgba(0,0,0,0.2)]"
style={{ maxHeight: PANEL_MAX_HEIGHT }}
>
<div className="flex items-start justify-between border-b border-border/70 px-4 py-4">
@ -412,7 +412,7 @@ export function SiteChatWidget() {
<button
type="button"
onClick={() => setIsOpen(false)}
className="inline-flex h-10 w-10 items-center justify-center rounded-full border border-border bg-background text-foreground transition hover:border-primary/50 hover:text-primary focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-primary/20"
className="inline-flex h-10 w-10 items-center justify-center rounded-full border border-border bg-white text-foreground transition hover:border-primary/50 hover:text-primary focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-primary/20"
aria-label="Close chat"
>
<X className="h-4 w-4" />
@ -422,7 +422,7 @@ export function SiteChatWidget() {
{!profile ? (
<div className="min-h-0 overflow-y-auto px-4 py-4">
<form onSubmit={handleProfileSubmit} className="space-y-4">
<div className="rounded-[1.5rem] border border-border/70 bg-background/80 p-4 shadow-sm">
<div className="rounded-[1.5rem] border border-border/70 bg-white p-4 shadow-sm">
<p className="text-sm font-medium text-foreground">Start with your details</p>
<p className="mt-1 text-xs leading-relaxed text-muted-foreground">
We use this to route the conversation to the right team member.
@ -469,7 +469,7 @@ export function SiteChatWidget() {
</div>
</div>
<div className="rounded-[1.5rem] border border-border/70 bg-background/80 p-4 shadow-sm">
<div className="rounded-[1.5rem] border border-border/70 bg-white p-4 shadow-sm">
<p className="text-sm font-medium text-foreground">Text updates</p>
<p className="mt-1 text-xs leading-relaxed text-muted-foreground">
Required service consent covers scheduling, support, repairs, moving, and follow-up texts for this request.
@ -479,7 +479,6 @@ export function SiteChatWidget() {
idPrefix="site-chat"
mode="chat"
serviceChecked={profileDraft.serviceTextConsent}
marketingChecked={profileDraft.marketingTextConsent}
onServiceChange={(checked) =>
setProfileDraft((current) => ({
...current,
@ -488,7 +487,6 @@ export function SiteChatWidget() {
consentSourcePage: pathname || "/",
}))
}
onMarketingChange={() => undefined}
serviceError={profileError && !profileDraft.serviceTextConsent ? profileError : undefined}
/>
</div>
@ -506,7 +504,7 @@ export function SiteChatWidget() {
<a
href={bootstrap.callUrl}
className="inline-flex min-h-11 items-center justify-center gap-2 rounded-full border border-border bg-background px-4 text-sm font-medium text-foreground transition hover:border-primary/50 hover:text-primary"
className="inline-flex min-h-11 items-center justify-center gap-2 rounded-full border border-border bg-white px-4 text-sm font-medium text-foreground transition hover:border-primary/50 hover:text-primary"
>
<Phone className="h-4 w-4" />
Call
@ -571,7 +569,7 @@ export function SiteChatWidget() {
</div>
</div>
<div className="border-t border-border/70 bg-background/95 px-4 py-4">
<div className="border-t border-border/70 bg-white px-4 py-4">
<form onSubmit={handleSubmit} className="space-y-3">
<label htmlFor="site-chat-input" className="text-sm font-semibold text-foreground">
Message
@ -585,7 +583,7 @@ export function SiteChatWidget() {
placeholder="Describe what you need"
rows={3}
disabled={isSending}
className="min-h-24 w-full rounded-2xl border border-border/70 bg-background px-4 py-3 text-sm text-foreground outline-none transition placeholder:text-muted-foreground focus:border-primary focus:ring-4 focus:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-60"
className="min-h-24 w-full rounded-2xl border border-border/70 bg-white px-4 py-3 text-sm text-foreground outline-none transition placeholder:text-muted-foreground focus:border-primary focus:ring-4 focus:ring-primary/15 disabled:cursor-not-allowed disabled:opacity-60"
/>
<SupportHint
@ -609,7 +607,7 @@ export function SiteChatWidget() {
<a
href={bootstrap.callUrl}
className="inline-flex min-h-11 items-center justify-center gap-2 rounded-full border border-border bg-background px-4 text-sm font-medium text-foreground transition hover:border-primary/50 hover:text-primary"
className="inline-flex min-h-11 items-center justify-center gap-2 rounded-full border border-border bg-white px-4 text-sm font-medium text-foreground transition hover:border-primary/50 hover:text-primary"
>
<Phone className="h-4 w-4" />
Call
@ -636,7 +634,7 @@ export function SiteChatWidget() {
type="button"
data-testid="site-chat-launcher"
onClick={() => setIsOpen(true)}
className="pointer-events-auto inline-flex h-14 w-14 items-center justify-center rounded-full border border-white/70 bg-background/95 shadow-[0_20px_60px_rgba(0,0,0,0.18)] transition hover:-translate-y-0.5 hover:shadow-[0_24px_68px_rgba(0,0,0,0.22)] focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-primary/20"
className="pointer-events-auto inline-flex h-14 w-14 items-center justify-center rounded-full border border-white/70 bg-white shadow-[0_20px_60px_rgba(0,0,0,0.18)] transition hover:-translate-y-0.5 hover:shadow-[0_24px_68px_rgba(0,0,0,0.22)] focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-primary/20"
aria-label={`Open chat with ${bootstrap.assistantName}`}
>
<AssistantAvatar src={bootstrap.avatarSrc} alt={bootstrap.assistantName} sizeClassName="h-12 w-12" />

View file

@ -13,7 +13,7 @@ const buttonVariants = cva(
destructive:
'bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
outline:
'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
'border bg-white shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
secondary:
'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost:

View file

@ -7,7 +7,7 @@ function Card({ className, ...props }: React.ComponentProps<'div'>) {
<div
data-slot="card"
className={cn(
'bg-card text-card-foreground flex flex-col gap-6 rounded-[1.75rem] border border-border/70 py-6 shadow-[0_18px_45px_rgba(15,23,42,0.08)]',
'bg-white text-card-foreground flex flex-col gap-6 rounded-[1.75rem] border border-border/70 py-6 shadow-[0_18px_45px_rgba(15,23,42,0.08)]',
className,
)}
{...props}

View file

@ -5,6 +5,7 @@ import { VendingMachinesShowcase } from "@/components/vending-machines-showcase"
import { CheckCircle2, CreditCard, MonitorSmartphone, Package, Wrench } from "lucide-react"
import Link from "next/link"
import { PublicInset, PublicPageHeader, PublicSurface } from "@/components/public-surface"
import { GetFreeMachineCta } from "@/components/get-free-machine-cta"
export function VendingMachinesPage() {
return (
@ -30,7 +31,7 @@ export function VendingMachinesPage() {
["Cashless payments", "Integrated card readers and secure payment options for modern locations."],
["Full service and support", "Maintenance, restocking, and local follow-up are part of the experience."],
].map(([title, body]) => (
<div key={title} className="flex items-start gap-4 rounded-[1.5rem] border border-border/60 bg-background/85 p-5 shadow-sm">
<div key={title} className="flex items-start gap-4 rounded-[1.5rem] border border-border/60 bg-white p-5 shadow-sm">
<CheckCircle2 className="mt-0.5 h-6 w-6 shrink-0 text-primary" />
<div>
<h3 className="text-lg font-semibold text-foreground">{title}</h3>
@ -51,9 +52,7 @@ export function VendingMachinesPage() {
<Button asChild size="lg" className="h-11 rounded-full px-6">
<Link href="/contact-us#contact-form">Contact Us</Link>
</Button>
<Button asChild size="lg" variant="outline" className="h-11 rounded-full px-6">
<Link href="/#request-machine">Get Free Machine</Link>
</Button>
<GetFreeMachineCta buttonLabel="Get Free Machine" className="h-11 px-6" variant="outline" />
</div>
</PublicSurface>
</section>

View file

@ -3,6 +3,7 @@
import { ReactNode } from "react"
import { Card, CardContent } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { GetFreeMachineCta } from "@/components/get-free-machine-cta"
import Link from "next/link"
import { CheckCircle2 } from "lucide-react"
@ -127,9 +128,11 @@ export function WhoWeServePage({ title, content }: WhoWeServePageProps) {
<Button asChild size="lg" className="bg-white text-[var(--primary)] hover:bg-white/90 text-lg h-12 px-8 font-semibold">
<Link href="/contact-us">Contact Us</Link>
</Button>
<Button asChild size="lg" variant="outline" className="bg-transparent border-2 border-white text-white hover:bg-white/10 text-lg h-12 px-8 font-semibold">
<Link href="/#request-machine">Get Free Machine</Link>
</Button>
<GetFreeMachineCta
buttonLabel="Get Free Machine"
className="h-12 border-2 border-white bg-transparent px-8 text-lg font-semibold text-white hover:bg-white/10"
variant="outline"
/>
</div>
</CardContent>
</Card>
@ -137,4 +140,3 @@ export function WhoWeServePage({ title, content }: WhoWeServePageProps) {
</div>
)
}