diff --git a/app/globals.css b/app/globals.css index 4bc4c9d..9f48bd2 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,125 +1,94 @@ @import "tailwindcss"; @import "tw-animate-css"; -@custom-variant dark (&:is(.dark *)); - -@theme inline { - --color-background: var(--background); - --color-foreground: var(--foreground); - --font-sans: var(--font-poppins); - --font-mono: var(--font-poppins); - --color-sidebar-ring: var(--sidebar-ring); - --color-sidebar-border: var(--sidebar-border); - --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); - --color-sidebar-accent: var(--sidebar-accent); - --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); - --color-sidebar-primary: var(--sidebar-primary); - --color-sidebar-foreground: var(--sidebar-foreground); - --color-sidebar: var(--sidebar); - --color-chart-5: var(--chart-5); - --color-chart-4: var(--chart-4); - --color-chart-3: var(--chart-3); - --color-chart-2: var(--chart-2); - --color-chart-1: var(--chart-1); - --color-ring: var(--ring); - --color-input: var(--input); - --color-border: var(--border); - --color-destructive: var(--destructive); - --color-accent-foreground: var(--accent-foreground); - --color-accent: var(--accent); - --color-muted-foreground: var(--muted-foreground); - --color-muted: var(--muted); - --color-secondary-foreground: var(--secondary-foreground); - --color-secondary: var(--secondary); - --color-primary-foreground: var(--primary-foreground); - --color-primary: var(--primary); - --color-popover-foreground: var(--popover-foreground); - --color-popover: var(--popover); - --color-card-foreground: var(--card-foreground); - --color-card: var(--card); - --radius-sm: calc(var(--radius) - 4px); - --radius-md: calc(var(--radius) - 2px); - --radius-lg: var(--radius); - --radius-xl: calc(var(--radius) + 4px); -} - :root { - --radius: 0.625rem; - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.205 0 0); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.97 0 0); - --sidebar-accent-foreground: oklch(0.205 0 0); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); + --foreground-rgb: 0, 0, 0; + --background-start-rgb: 214, 219, 220; + --background-end-rgb: 255, 255, 255; } -.dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.205 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.205 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.922 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.704 0.191 22.216); - --border: oklch(1 0 0 / 10%); - --input: oklch(1 0 0 / 15%); - --ring: oklch(0.556 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(1 0 0 / 10%); - --sidebar-ring: oklch(0.556 0 0); +@media (prefers-color-scheme: dark) { + :root { + --foreground-rgb: 255, 255, 255; + --background-start-rgb: 0, 0, 0; + --background-end-rgb: 0, 0, 0; + } +} + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 0 0% 3.9%; + --card: 0 0% 100%; + --card-foreground: 0 0% 3.9%; + --popover: 0 0% 100%; + --popover-foreground: 0 0% 3.9%; + --primary: 0 0% 9%; + --primary-foreground: 0 0% 98%; + --secondary: 0 0% 96.1%; + --secondary-foreground: 0 0% 9%; + --muted: 0 0% 96.1%; + --muted-foreground: 0 0% 45.1%; + --accent: 0 0% 96.1%; + --accent-foreground: 0 0% 9%; + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 89.8%; + --input: 0 0% 89.8%; + --ring: 0 0% 3.9%; + --chart-1: 12 76% 61%; + --chart-2: 173 58% 39%; + --chart-3: 197 37% 24%; + --chart-4: 43 74% 66%; + --chart-5: 27 87% 67%; + --radius: 0.5rem; + } + .dark { + --background: 0 0% 3.9%; + --foreground: 0 0% 98%; + --card: 0 0% 3.9%; + --card-foreground: 0 0% 98%; + --popover: 0 0% 3.9%; + --popover-foreground: 0 0% 98%; + --primary: 0 0% 98%; + --primary-foreground: 0 0% 9%; + --secondary: 0 0% 14.9%; + --secondary-foreground: 0 0% 98%; + --muted: 0 0% 14.9%; + --muted-foreground: 0 0% 63.9%; + --accent: 0 0% 14.9%; + --accent-foreground: 0 0% 98%; + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 0 0% 98%; + --border: 0 0% 14.9%; + --input: 0 0% 14.9%; + --ring: 0 0% 83.1%; + --chart-1: 220 70% 50%; + --chart-2: 160 60% 45%; + --chart-3: 30 80% 55%; + --chart-4: 280 65% 60%; + --chart-5: 340 75% 55%; + } } @layer base { * { - @apply border-border outline-ring/50; + border-color: hsl(var(--border)); } body { - @apply bg-background text-foreground; + background-color: #ffffff; + color: hsl(var(--foreground)); } - body.menu-open { - overflow: hidden; + html.dark body { + background-color: #1a1e26; + } + html { + scroll-behavior: smooth; + } +} + +@layer utilities { + .text-balance { + text-wrap: balance; } } diff --git a/app/layout.tsx b/app/layout.tsx index affedce..5b3bb9b 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,29 +1,28 @@ -import type { Metadata } from "next"; -import { Poppins } from "next/font/google"; -import "./globals.css"; +import './globals.css'; +import type { Metadata } from 'next'; +import { Inter } from 'next/font/google'; +import { Providers } from './providers'; +import { Toaster } from '@/components/ui/toaster'; -const poppins = Poppins({ - variable: "--font-poppins", - subsets: ["latin"], - weight: ["300", "400", "500", "600", "700"], -}); +const inter = Inter({ subsets: ['latin'] }); export const metadata: Metadata = { - title: "Attune Heart Therapy", - description: "Attune Heart Therapy", + title: 'Attune Heart Therapy | Nathalie Mac Guffie, LCSW | Miami, FL', + description: 'Compassionate, evidence-based therapy in Miami, FL. Licensed Clinical Social Worker offering anxiety, depression, trauma therapy and more.', }; export default function RootLayout({ children, -}: Readonly<{ +}: { children: React.ReactNode; -}>) { +}) { return ( - - - {children} + + + + {children} + + ); diff --git a/app/page.tsx b/app/page.tsx index 295f8fd..fced93b 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,65 +1,22 @@ -import Image from "next/image"; +import Section from "../components/Section"; +import { Footer } from "../components/Footer"; +import { HeroSection } from "@/components/Hero"; +import { About } from "@/components/About"; +import { Services } from "@/components/Services"; +import { ContactSection } from "@/components/ContactSection"; export default function Home() { return ( -
-
- Next.js logo -
-

- To get started, edit the page.tsx file. -

-

- Looking for a starting point or more instructions? Head over to{" "} - - Templates - {" "} - or the{" "} - - Learning - {" "} - center. -

-
-
- - Vercel logomark - Deploy Now - - - Documentation - -
-
-
+
+ + + + + + + + +
); } diff --git a/app/providers.tsx b/app/providers.tsx new file mode 100644 index 0000000..e759ace --- /dev/null +++ b/app/providers.tsx @@ -0,0 +1,15 @@ +"use client"; + +import { ThemeProvider } from "../components/ThemeProvider"; +import { Navbar } from "../components/Navbar"; +import { type ReactNode } from "react"; + +export function Providers({ children }: { children: ReactNode }) { + return ( + + + {children} + + ); +} + diff --git a/components/About.tsx b/components/About.tsx new file mode 100644 index 0000000..dbc69fe --- /dev/null +++ b/components/About.tsx @@ -0,0 +1,201 @@ +'use client'; + +import { motion } from "framer-motion"; +import { useInView } from "framer-motion"; +import { useRef, useEffect, useState } from "react"; +import { Award, Heart, Users } from "lucide-react"; + +export function About() { + const ref = useRef(null); + const isInView = useInView(ref, { once: true, margin: "-100px" }); + const [isDark, setIsDark] = useState(false); + + useEffect(() => { + const checkTheme = () => { + setIsDark(document.documentElement.classList.contains('dark')); + }; + + checkTheme(); + const observer = new MutationObserver(checkTheme); + observer.observe(document.documentElement, { + attributes: true, + attributeFilter: ['class'] + }); + + return () => observer.disconnect(); + }, []); + + const credentials = [ + { + icon: Award, + title: "Licensed Mental Health Counselor (LMHC)", + description: "Florida licensed with 30 years of experience", + }, + { + icon: Heart, + title: "Trauma-Focused Specialist", + description: "Certified in TF-CBT for trauma recovery", + }, + { + icon: Users, + title: "Infant Mental Health & Play Therapy", + description: "Registered Play Therapist (RPT-S) and IMH Endorsement", + }, + ]; + + return ( +
+
+ {!isDark && ( +
+ )} + {isDark && ( +
+ )} + +
+ + +
+ +
+ + + Meet Nathalie Mac-Guffie + + + A dedicated mental health professional specializing in helping children + under 10 and their families navigate trauma, emotional challenges, and + developmental needs. + + + +
+ +
+ + My Approach + +

+ I provide person-centered guidance, following your child's lead while + drawing out their strengths and incorporating effective coping skills. + My interventions are relationship-based, creating a warm, non-judgmental + space for growth and healing. +

+

+ Together, we'll set realistic, measurable, and achievable goals with + clear objectives tailored to your family's unique needs. +

+
+
+ + + {credentials.map((cred, index) => { + const Icon = cred.icon; + return ( + +
+ + + +
+ + {cred.title} + + + {cred.description} + +
+
+
+ ); + })} +
+
+
+
+ ); +} + diff --git a/components/ContactSection.tsx b/components/ContactSection.tsx new file mode 100644 index 0000000..088e3d7 --- /dev/null +++ b/components/ContactSection.tsx @@ -0,0 +1,181 @@ +"use client"; + +import { motion, useInView } from "framer-motion"; +import { useEffect, useRef, useState } from "react"; +import { Send } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Textarea } from "@/components/ui/textarea"; +import { Card, CardContent } from "@/components/ui/card"; +import { toast } from "sonner"; + +export function ContactSection() { + const ref = useRef(null); + const isInView = useInView(ref, { once: true, margin: "-100px" }); + const [isDark, setIsDark] = useState(false); + const [formData, setFormData] = useState({ + name: "", + email: "", + phone: "", + message: "", + }); + + // Sync with global theme class like Navbar/Hero/About + useEffect(() => { + const sync = () => setIsDark(document.documentElement.classList.contains("dark")); + sync(); + const observer = new MutationObserver(sync); + observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] }); + return () => observer.disconnect(); + }, []); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + toast("Message Received", { + description: "Thank you for reaching out. We'll get back to you soon!", + }); + setFormData({ name: "", email: "", phone: "", message: "" }); + }; + + return ( +
+ {/* Theme sync like Hero/About/Navbar */} +
+ {!isDark && ( +
+ )} + {isDark && ( +
+ )} + + {/* Subtle animated blobs */} +
+ + +
+ +
+ +

+ Get in Touch +

+
+

+ Ready to start your journey? Reach out to schedule a consultation. +

+ + +
+ {/* Left: Illustration replacing cards */} + + + + {/* Use a high-quality, license-friendly illustration */} +
+ Contact illustration + +
+
+

Let's Begin Your Healing Journey

+

+ Taking the first step toward therapy can feel daunting, but you're not alone. I'm here to support + you through every stage of your journey toward wellness and growth. +

+
+
+
+
+ + {/* Right: Contact form */} + + + +

Send a Message

+
+
+ setFormData({ ...formData, name: e.target.value })} + required + className="bg-card text-foreground dark:text-zinc-100 placeholder:text-muted-foreground dark:placeholder:text-zinc-400 border-border focus-visible:ring-rose-500" + /> +
+
+ setFormData({ ...formData, email: e.target.value })} + required + className="bg-card text-foreground dark:text-zinc-100 placeholder:text-muted-foreground dark:placeholder:text-zinc-400 border-border focus-visible:ring-rose-500" + /> +
+
+ setFormData({ ...formData, phone: e.target.value })} + className="bg-card text-foreground dark:text-zinc-100 placeholder:text-muted-foreground dark:placeholder:text-zinc-400 border-border focus-visible:ring-rose-500" + /> +
+
+