diff --git a/src/components/PatientBanner.tsx b/src/components/PatientBanner.tsx
new file mode 100644
index 0000000..a3831c8
--- /dev/null
+++ b/src/components/PatientBanner.tsx
@@ -0,0 +1,189 @@
+import { Download, Mail, Linkedin } from 'lucide-react'
+import { patient } from '@/data/patient'
+import { useScrollCondensation } from '@/hooks/useScrollCondensation'
+
+export function PatientBanner() {
+ const { isCondensed, sentinelRef } = useScrollCondensation({ threshold: 100 })
+
+ return (
+ <>
+
+
+ {isCondensed ? (
+
+ ) : (
+
+ )}
+
+ >
+ )
+}
+
+function FullBanner() {
+ return (
+
+
+
+
+
+ {patient.name}
+
+
+ {patient.status}
+
+
+
+
+ DOB: {patient.dob}
+
+ |
+
+ NHS No:{' '}
+
+ {patient.nhsNumber}
+
+
+ |
+ {patient.address}
+
+
+
+
+
}
+ label="Download CV"
+ href="/cv.pdf"
+ />
+
}
+ label="Email"
+ href={`mailto:${patient.email}`}
+ />
+
}
+ label="LinkedIn"
+ href={`https://${patient.linkedin}`}
+ external
+ />
+
+
+
+ )
+}
+
+function CondensedBanner() {
+ return (
+
+
+
+ {patient.name}
+
+ |
+
+ NHS No:{' '}
+
+ {patient.nhsNumber}
+
+
+ |
+
+
+
+
}
+ label="Download CV"
+ href="/cv.pdf"
+ compact
+ />
+
}
+ label="Email"
+ href={`mailto:${patient.email}`}
+ compact
+ />
+
+
+ )
+}
+
+interface StatusDotProps {
+ status: string
+}
+
+function StatusDot({ status }: StatusDotProps) {
+ const colorClass = status === 'Active' ? 'bg-pmr-green' : 'bg-slate-400'
+ return (
+
+ )
+}
+
+interface StatusBadgeProps {
+ badge: string
+}
+
+function StatusBadge({ badge }: StatusBadgeProps) {
+ return (
+
+ {badge}
+
+ )
+}
+
+interface ActionButtonProps {
+ icon: React.ReactNode
+ label: string
+ href: string
+ external?: boolean
+ compact?: boolean
+}
+
+function ActionButton({ icon, label, href, external, compact }: ActionButtonProps) {
+ return (
+
+ {icon}
+ {label}
+
+ )
+}
diff --git a/src/hooks/useScrollCondensation.ts b/src/hooks/useScrollCondensation.ts
new file mode 100644
index 0000000..39736e3
--- /dev/null
+++ b/src/hooks/useScrollCondensation.ts
@@ -0,0 +1,35 @@
+import { useState, useEffect, useRef } from 'react'
+
+interface UseScrollCondensationOptions {
+ threshold?: number
+}
+
+export function useScrollCondensation(options: UseScrollCondensationOptions = {}) {
+ const { threshold = 100 } = options
+ const [isCondensed, setIsCondensed] = useState(false)
+ const sentinelRef = useRef(null)
+
+ useEffect(() => {
+ const sentinel = sentinelRef.current
+ if (!sentinel) return
+
+ const observer = new IntersectionObserver(
+ (entries) => {
+ const [entry] = entries
+ setIsCondensed(!entry.isIntersecting)
+ },
+ {
+ rootMargin: `-${threshold}px 0px 0px 0px`,
+ threshold: 0,
+ }
+ )
+
+ observer.observe(sentinel)
+
+ return () => {
+ observer.disconnect()
+ }
+ }, [threshold])
+
+ return { isCondensed, sentinelRef }
+}