feat: iPad portrait responsive layout — min-[820px] breakpoints across all blocks + tablet slide-in nav

This commit is contained in:
Jeffrey 2026-02-24 12:18:36 +01:00
parent 7010e6519b
commit 313cfd31fb
13 changed files with 59 additions and 54 deletions

View File

@ -56,7 +56,6 @@ function groupChildren(children: NavChild[]): { heading: string | null; links: N
return result return result
} }
/* ── Priority #4: Focus trap hook for mobile menu ──────────────────── */
function useFocusTrap(containerRef: React.RefObject<HTMLElement | null>, active: boolean) { function useFocusTrap(containerRef: React.RefObject<HTMLElement | null>, active: boolean) {
useEffect(() => { useEffect(() => {
if (!active || !containerRef.current) return if (!active || !containerRef.current) return
@ -68,10 +67,8 @@ function useFocusTrap(containerRef: React.RefObject<HTMLElement | null>, active:
const getFocusableElements = () => const getFocusableElements = () =>
Array.from(container.querySelectorAll<HTMLElement>(focusableSelector)) Array.from(container.querySelectorAll<HTMLElement>(focusableSelector))
// Focus the first focusable element when trap activates
const elements = getFocusableElements() const elements = getFocusableElements()
if (elements.length > 0) { if (elements.length > 0) {
// Small delay to ensure the menu transition has started
setTimeout(() => elements[0]?.focus(), 100) setTimeout(() => elements[0]?.focus(), 100)
} }
@ -102,16 +99,13 @@ function useFocusTrap(containerRef: React.RefObject<HTMLElement | null>, active:
}, [active, containerRef]) }, [active, containerRef])
} }
/* ── Priority #10: Check if a nav item matches current path ────────── */
function isActiveSection(item: NavItem, pathname: string | null): boolean { function isActiveSection(item: NavItem, pathname: string | null): boolean {
if (!pathname || !item.children?.length) { if (!pathname || !item.children?.length) {
// For top-level links without children, check direct href match
const href = resolveHref(item) const href = resolveHref(item)
if (href === '/') return pathname === '/' if (href === '/') return pathname === '/'
return pathname?.startsWith(href) || false return pathname?.startsWith(href) || false
} }
// For dropdown parents, check if any child href matches
return item.children.some((child) => { return item.children.some((child) => {
const childHref = resolveHref(child) const childHref = resolveHref(child)
if (childHref === '/' || childHref === '#') return false if (childHref === '/' || childHref === '#') return false
@ -119,7 +113,6 @@ function isActiveSection(item: NavItem, pathname: string | null): boolean {
}) })
} }
const MegaMenuPanel: React.FC<{ const MegaMenuPanel: React.FC<{
item: NavItem item: NavItem
headerRef: React.RefObject<HTMLElement | null> headerRef: React.RefObject<HTMLElement | null>
@ -155,7 +148,7 @@ const MegaMenuPanel: React.FC<{
onClick={onClose} onClick={onClose}
/> />
{/* Panel — white in light, navy in dark */} {/* Panel */}
<div <div
ref={panelRef} ref={panelRef}
className="fixed left-0 right-0 z-40 bg-white dark:bg-fd-navy border-b border-fd-navy/10 dark:border-white/10" className="fixed left-0 right-0 z-40 bg-white dark:bg-fd-navy border-b border-fd-navy/10 dark:border-white/10"
@ -222,7 +215,6 @@ export const HeaderNav: React.FC<{ data: HeaderType; socialLinks?: SocialLinkDat
const megaMenuRef = useRef<HTMLDivElement | null>(null) const megaMenuRef = useRef<HTMLDivElement | null>(null)
const mobileMenuRef = useRef<HTMLDivElement | null>(null) const mobileMenuRef = useRef<HTMLDivElement | null>(null)
// Priority #4: Focus trap
useFocusTrap(mobileMenuRef, mobileOpen) useFocusTrap(mobileMenuRef, mobileOpen)
useEffect(() => { useEffect(() => {
@ -275,13 +267,12 @@ export const HeaderNav: React.FC<{ data: HeaderType; socialLinks?: SocialLinkDat
return ( return (
<> <>
{/* ── Desktop nav ── */} {/* ── Desktop nav — shows at lg (1024px+) ── */}
<nav ref={navRef} className="hidden md:flex gap-6 items-center"> <nav ref={navRef} className="hidden lg:flex gap-6 items-center">
{navItems.map((item, i) => { {navItems.map((item, i) => {
const hasChildren = item.children && item.children.length > 0 const hasChildren = item.children && item.children.length > 0
const isOpen = openDropdown === item.label const isOpen = openDropdown === item.label
const isMega = item.megaMenu && hasChildren const isMega = item.megaMenu && hasChildren
// Priority #10: Active section detection
const isActive = isActiveSection(item, pathname) const isActive = isActiveSection(item, pathname)
return hasChildren ? ( return hasChildren ? (
@ -302,7 +293,6 @@ export const HeaderNav: React.FC<{ data: HeaderType; socialLinks?: SocialLinkDat
<ChevronDownIcon <ChevronDownIcon
className={`w-4 h-4 transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`} className={`w-4 h-4 transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}
/> />
{/* Active indicator dot */}
{isActive && !isOpen && ( {isActive && !isOpen && (
<span className="absolute -bottom-1 left-1/2 -translate-x-1/2 w-1 h-1 rounded-full bg-fd-yellow" /> <span className="absolute -bottom-1 left-1/2 -translate-x-1/2 w-1 h-1 rounded-full bg-fd-yellow" />
)} )}
@ -361,27 +351,42 @@ export const HeaderNav: React.FC<{ data: HeaderType; socialLinks?: SocialLinkDat
/> />
)} )}
{/* ── Mobile hamburger ── */} {/* ── Hamburger — shows below lg (mobile + tablet) ── */}
<button <button
className="md:hidden text-fd-navy dark:text-white p-2" className="lg:hidden text-fd-navy dark:text-white p-2"
onClick={() => setMobileOpen(!mobileOpen)} onClick={() => setMobileOpen(!mobileOpen)}
aria-label={mobileOpen ? 'Stäng meny' : 'Öppna meny'} aria-label={mobileOpen ? 'Stäng meny' : 'Öppna meny'}
> >
{mobileOpen ? <XIcon className="w-6 h-6" /> : <MenuIcon className="w-6 h-6" />} {mobileOpen ? <XIcon className="w-6 h-6" /> : <MenuIcon className="w-6 h-6" />}
</button> </button>
{/* ── Mobile full-screen overlay (Priority #4: has focus trap via ref) ── */} {/* ── Tablet backdrop — blur overlay left of panel on md+ ── */}
<div
className={`fixed inset-0 z-40 lg:hidden transition-opacity duration-300 ${
mobileOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'
}`}
style={{ backdropFilter: 'blur(4px)', WebkitBackdropFilter: 'blur(4px)', backgroundColor: 'rgba(14, 35, 56, 0.45)' }}
onClick={closeMobile}
aria-hidden="true"
/>
{/* Mobile/tablet slide-in panel
Mobile (<768px): full-screen overlay
Tablet (768-1023px): right-side panel, 420px wide, with backdrop above
*/}
<div <div
ref={mobileMenuRef} ref={mobileMenuRef}
className={`fixed inset-0 z-50 bg-fd-navy flex flex-col transition-transform duration-300 md:hidden ${ className={`fixed inset-y-0 right-0 z-50 flex flex-col bg-fd-navy lg:hidden
mobileOpen ? 'translate-x-0' : 'translate-x-full' w-full md:w-[420px]
}`} transition-transform duration-300
${mobileOpen ? 'translate-x-0 md:shadow-[-24px_0_60px_rgba(0,0,0,0.25)]' : 'translate-x-full'}
`}
role="dialog" role="dialog"
aria-modal="true" aria-modal="true"
aria-label="Navigeringsmeny" aria-label="Navigeringsmeny"
> >
{/* Header bar */} {/* Header bar */}
<div className="flex items-center justify-between px-6 py-5 border-b border-white/10"> <div className="flex items-center justify-between px-6 md:px-8 py-5 border-b border-white/10">
<Link href="/" onClick={closeMobile}> <Link href="/" onClick={closeMobile}>
<span className="font-joey-heavy text-fd-yellow text-xl">Fiber Direkt</span> <span className="font-joey-heavy text-fd-yellow text-xl">Fiber Direkt</span>
</Link> </Link>
@ -395,7 +400,7 @@ export const HeaderNav: React.FC<{ data: HeaderType; socialLinks?: SocialLinkDat
</div> </div>
{/* Nav links */} {/* Nav links */}
<nav className="flex-1 overflow-y-auto px-6 py-6 flex flex-col"> <nav className="flex-1 overflow-y-auto px-6 md:px-8 py-6 flex flex-col">
{navItems.map((item, i) => { {navItems.map((item, i) => {
const hasChildren = item.children && item.children.length > 0 const hasChildren = item.children && item.children.length > 0
const isExpanded = mobileOpenSection === item.label const isExpanded = mobileOpenSection === item.label
@ -404,7 +409,7 @@ export const HeaderNav: React.FC<{ data: HeaderType; socialLinks?: SocialLinkDat
<div key={i} className="border-b border-white/10"> <div key={i} className="border-b border-white/10">
<button <button
onClick={() => setMobileOpenSection(isExpanded ? null : item.label ?? null)} onClick={() => setMobileOpenSection(isExpanded ? null : item.label ?? null)}
className="w-full flex justify-between items-center py-4 text-white font-joey-medium text-xl hover:text-fd-yellow transition-colors" className="w-full flex justify-between items-center py-4 md:py-5 text-white font-joey-medium text-xl md:text-2xl hover:text-fd-yellow transition-colors"
> >
{item.label} {item.label}
<ChevronRightIcon <ChevronRightIcon
@ -421,7 +426,7 @@ export const HeaderNav: React.FC<{ data: HeaderType; socialLinks?: SocialLinkDat
key={j} key={j}
href={resolveHref(child)} href={resolveHref(child)}
onClick={closeMobile} onClick={closeMobile}
className="block pl-4 py-3 text-fd-yellow font-joey text-lg border-b border-white/5 hover:text-white transition-colors" className="block pl-4 py-3 md:py-3.5 text-fd-yellow font-joey text-lg md:text-xl border-b border-white/5 hover:text-white transition-colors"
> >
{child.label} {child.label}
</Link> </Link>
@ -433,7 +438,7 @@ export const HeaderNav: React.FC<{ data: HeaderType; socialLinks?: SocialLinkDat
key={i} key={i}
href={resolveHref(item)} href={resolveHref(item)}
onClick={closeMobile} onClick={closeMobile}
className="py-4 text-white font-joey-medium text-xl border-b border-white/10 hover:text-fd-yellow transition-colors block" className="py-4 md:py-5 text-white font-joey-medium text-xl md:text-2xl border-b border-white/10 hover:text-fd-yellow transition-colors block"
> >
{item.label} {item.label}
</Link> </Link>
@ -441,8 +446,8 @@ export const HeaderNav: React.FC<{ data: HeaderType; socialLinks?: SocialLinkDat
})} })}
</nav> </nav>
{/* ── Mobile menu footer: flag left, social icons right ── */} {/* Footer: Swedish flag left, social icons right */}
<div className="px-6 py-5 border-t border-white/10 flex items-center justify-between"> <div className="px-6 md:px-8 py-5 border-t border-white/10 flex items-center justify-between">
<SwedishFlag /> <SwedishFlag />
{socialLinks.length > 0 && ( {socialLinks.length > 0 && (
<SocialIconsRow <SocialIconsRow

View File

@ -50,10 +50,10 @@ const sectionBgMap: Record<string, string> = {
} }
const layoutGridMap: Record<string, string> = { const layoutGridMap: Record<string, string> = {
'1-2': 'lg:grid-cols-[1fr_2fr]', '1-2': 'min-[820px]:grid-cols-[1fr_2fr]',
'2-1': 'lg:grid-cols-[2fr_1fr]', '2-1': 'min-[820px]:grid-cols-[2fr_1fr]',
'1-1-1': 'lg:grid-cols-3', '1-1-1': 'min-[820px]:grid-cols-3',
'1-1': 'lg:grid-cols-2', '1-1': 'min-[820px]:grid-cols-2',
} }
const styleClassMap: Record<string, string> = { const styleClassMap: Record<string, string> = {
@ -80,7 +80,7 @@ export const FDCardGridBlockComponent: React.FC<FDCardGridBlockProps> = ({
return ( return (
<section id={anchorId || undefined} className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}> <section id={anchorId || undefined} className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
<div className="max-w-[1200px] mx-auto px-6 md:px-8"> <div className="max-w-[1200px] mx-auto px-6 md:px-8">
<div className={`grid grid-cols-1 md:grid-cols-2 ${gridCols} gap-4 md:gap-6`}> <div className={`grid grid-cols-1 ${gridCols} gap-4 md:gap-6`}>
{cards?.map((card, index) => { {cards?.map((card, index) => {
const mode = card.displayMode || 'content' const mode = card.displayMode || 'content'

View File

@ -48,7 +48,7 @@ export const FDCtaSideImageBlockComponent: React.FC<FDCtaSideImageBlockProps> =
: 'text-fd-navy dark:text-white' : 'text-fd-navy dark:text-white'
const textContent = ( const textContent = (
<div className={`flex flex-col flex-1 items-start gap-8 lg:gap-[41px] ${!hasImage ? 'max-w-2xl' : ''}`}> <div className={`flex flex-col flex-1 items-start gap-8 min-[820px]:gap-[41px] ${!hasImage ? 'max-w-2xl' : ''}`}>
<div className="flex flex-col items-start gap-4 w-full"> <div className="flex flex-col items-start gap-4 w-full">
<h2 className={`w-full font-joey-heavy text-fd-h1 leading-tight ${headingClass}`}> <h2 className={`w-full font-joey-heavy text-fd-h1 leading-tight ${headingClass}`}>
{heading} {heading}
@ -67,7 +67,7 @@ export const FDCtaSideImageBlockComponent: React.FC<FDCtaSideImageBlockProps> =
) )
const imageContent = hasImage ? ( const imageContent = hasImage ? (
<div className={`relative w-full lg:w-[575px] lg:h-[479px] flex-shrink-0 overflow-hidden ${imageRadius}`}> <div className={`relative w-full min-[820px]:w-[45%] lg:w-[575px] lg:h-[479px] flex-shrink-0 overflow-hidden ${imageRadius}`}>
<FDImage <FDImage
media={image as Media} media={image as Media}
size="large" size="large"
@ -81,7 +81,7 @@ export const FDCtaSideImageBlockComponent: React.FC<FDCtaSideImageBlockProps> =
return ( return (
<section id={anchorId || undefined} className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}> <section id={anchorId || undefined} className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
<div className="max-w-[1200px] mx-auto px-6 md:px-8 flex flex-col lg:flex-row items-center gap-10 lg:gap-16"> <div className="max-w-[1200px] mx-auto px-6 md:px-8 flex flex-col min-[820px]:flex-row items-center gap-10 min-[820px]:gap-16">
{imagePosition === 'left' ? ( {imagePosition === 'left' ? (
<>{imageContent}{textContent}</> <>{imageContent}{textContent}</>
) : ( ) : (

View File

@ -56,7 +56,7 @@ export const FDLocationsGridBlockComponent: React.FC<Props> = ({
</div> </div>
)} )}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-6"> <div className="grid grid-cols-1 sm:grid-cols-2 min-[820px]:grid-cols-3 gap-4 md:gap-6">
{(cards ?? []).map((card, i) => { {(cards ?? []).map((card, i) => {
const media = card.image as Media | undefined const media = card.image as Media | undefined
const isLink = Boolean(card.link) const isLink = Boolean(card.link)

View File

@ -64,9 +64,9 @@ const buttonVariantMap: Record<string, { variant: 'primary' | 'outline' }> = {
} }
const gridColsMap: Record<number, string> = { const gridColsMap: Record<number, string> = {
1: 'lg:grid-cols-1 max-w-[500px] mx-auto', 1: 'min-[820px]:grid-cols-1 max-w-[500px] mx-auto',
2: 'lg:grid-cols-2', 2: 'min-[820px]:grid-cols-2',
3: 'lg:grid-cols-3', 3: 'min-[820px]:grid-cols-3',
} }
const cardRadius = 'rounded-[32px] md:rounded-[50px] lg:rounded-[70px]' const cardRadius = 'rounded-[32px] md:rounded-[50px] lg:rounded-[70px]'
@ -96,11 +96,11 @@ export const FDPricingCardBlockComponent: React.FC<FDPricingCardBlockProps> = ({
{sectionTitle} {sectionTitle}
</h2> </h2>
)} )}
<div className={`grid grid-cols-1 ${gridCols} gap-6 md:gap-8`}> <div className={`grid grid-cols-1 ${gridCols} gap-4 min-[820px]:gap-5 lg:gap-8`}>
{cards?.map((card, index) => ( {cards?.map((card, index) => (
<div <div
key={index} key={index}
className={`${style.bg} ${style.border} ${cardRadius} px-8 md:px-12 py-10 md:py-14 flex flex-col gap-5`} className={`${style.bg} ${style.border} ${cardRadius} px-6 min-[820px]:px-8 lg:px-12 py-8 min-[820px]:py-10 lg:py-14 flex flex-col gap-5`}
> >
<h3 className={`font-joey-heavy text-fd-h2 leading-tight ${style.title}`}> <h3 className={`font-joey-heavy text-fd-h2 leading-tight ${style.title}`}>
{card.title} {card.title}

View File

@ -219,10 +219,10 @@ export const FDServiceCalculatorBlockComponent: React.FC<Props> = ({
</div> </div>
)} )}
<div className="grid grid-cols-1 lg:grid-cols-5 gap-6 lg:gap-8"> <div className="grid grid-cols-1 min-[820px]:grid-cols-5 gap-6 min-[820px]:gap-8">
{/* ── Left: Configuration ─────────────────────────────────── */} {/* ── Left: Configuration ─────────────────────────────────── */}
<div className={`lg:col-span-3 p-7 md:p-9 ${cardClass}`}> <div className={`min-[820px]:col-span-3 p-7 md:p-9 ${cardClass}`}>
{/* Option groups */} {/* Option groups */}
{(optionGroups ?? []).map((group, gi) => ( {(optionGroups ?? []).map((group, gi) => (
@ -312,7 +312,7 @@ export const FDServiceCalculatorBlockComponent: React.FC<Props> = ({
</div> </div>
{/* ── Right: Summary ──────────────────────────────────────── */} {/* ── Right: Summary ──────────────────────────────────────── */}
<div className={`lg:col-span-2 p-7 md:p-9 flex flex-col ${cardClass}`}> <div className={`min-[820px]:col-span-2 p-7 md:p-9 flex flex-col ${cardClass}`}>
<h3 className={`font-joey-heavy text-fd-h2 mb-6 ${headingColor}`}>{summaryHeading}</h3> <h3 className={`font-joey-heavy text-fd-h2 mb-6 ${headingColor}`}>{summaryHeading}</h3>
<div className="flex-1 space-y-0"> <div className="flex-1 space-y-0">

View File

@ -100,7 +100,7 @@ export const FDServiceChooserBlockComponent: React.FC<Props> = ({
</p> </p>
)} )}
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-6"> <div className="grid grid-cols-1 sm:grid-cols-2 min-[820px]:grid-cols-3 gap-4 md:gap-6">
{activeCategory?.services?.map((service, i) => ( {activeCategory?.services?.map((service, i) => (
<div <div
key={i} key={i}

View File

@ -4,8 +4,8 @@ import { FDImage } from '@/components/FDImage'
const columnClasses: Record<string, string> = { const columnClasses: Record<string, string> = {
'2': 'grid-cols-1 md:grid-cols-2', '2': 'grid-cols-1 md:grid-cols-2',
'3': 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3', '3': 'grid-cols-1 md:grid-cols-2 min-[820px]:grid-cols-3',
'4': 'grid-cols-2 lg:grid-cols-4', '4': 'grid-cols-2 min-[820px]:grid-cols-4',
} }
/* Priority #5: Responsive radius for service images */ /* Priority #5: Responsive radius for service images */

View File

@ -34,8 +34,8 @@ const cardMap: Record<string, { bg: string; name: string; role: string; bio: str
const colsMap: Record<string, string> = { const colsMap: Record<string, string> = {
'2': 'sm:grid-cols-2', '2': 'sm:grid-cols-2',
'3': 'sm:grid-cols-2 lg:grid-cols-3', '3': 'sm:grid-cols-2 min-[820px]:grid-cols-3',
'4': 'sm:grid-cols-2 lg:grid-cols-4', '4': 'sm:grid-cols-2 min-[820px]:grid-cols-4',
} }
/* Priority #5: Responsive radius for team member cards */ /* Priority #5: Responsive radius for team member cards */

View File

@ -121,7 +121,7 @@ export const FDTestimonialBlockComponent: React.FC<FDTestimonialBlockProps> = ({
)} )}
</div> </div>
) : ( ) : (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div className="grid grid-cols-1 md:grid-cols-2 min-[820px]:grid-cols-3 gap-6">
{testimonials?.map((t, i) => { {testimonials?.map((t, i) => {
const avatar = t.avatar as Media | undefined const avatar = t.avatar as Media | undefined
return ( return (

View File

@ -78,7 +78,7 @@ export const FDUspChecklistBlockComponent: React.FC<FDUspChecklistBlockProps> =
return ( return (
<section id={anchorId || undefined} className={`w-full py-16 md:py-20 lg:py-[99px] ${bg}`}> <section id={anchorId || undefined} className={`w-full py-16 md:py-20 lg:py-[99px] ${bg}`}>
<div className="max-w-[1200px] mx-auto px-6 md:px-8 flex flex-col lg:flex-row items-center gap-10 lg:gap-16"> <div className="max-w-[1200px] mx-auto px-6 md:px-8 flex flex-col min-[820px]:flex-row items-center gap-10 min-[820px]:gap-16">
{imagePosition === 'left' ? <>{imageContent}{textContent}</> : <>{textContent}{imageContent}</>} {imagePosition === 'left' ? <>{imageContent}{textContent}</> : <>{textContent}{imageContent}</>}
</div> </div>
</section> </section>

View File

@ -169,10 +169,10 @@ export const FDVpsCalculatorBlockComponent: React.FC<FDVpsCalculatorBlockProps>
</div> </div>
)} )}
<div className="grid grid-cols-1 lg:grid-cols-5 gap-6 lg:gap-8"> <div className="grid grid-cols-1 min-[820px]:grid-cols-5 gap-6 min-[820px]:gap-8">
{/* Left: Config */} {/* Left: Config */}
<div className={`lg:col-span-3 p-7 md:p-9 ${cardClass}`}> <div className={`min-[820px]:col-span-3 p-7 md:p-9 ${cardClass}`}>
<p className={`font-joey-medium text-fd-body tracking-widest uppercase mb-3 ${sectionLabel}`}> <p className={`font-joey-medium text-fd-body tracking-widest uppercase mb-3 ${sectionLabel}`}>
Operativsystem Operativsystem
@ -225,7 +225,7 @@ export const FDVpsCalculatorBlockComponent: React.FC<FDVpsCalculatorBlockProps>
</div> </div>
{/* Right: Summary */} {/* Right: Summary */}
<div className={`lg:col-span-2 p-7 md:p-9 flex flex-col ${cardClass}`}> <div className={`min-[820px]:col-span-2 p-7 md:p-9 flex flex-col ${cardClass}`}>
<h3 className={`font-joey-heavy text-fd-h2 mb-6 ${headingColor}`}>Kostnadsöversikt</h3> <h3 className={`font-joey-heavy text-fd-h2 mb-6 ${headingColor}`}>Kostnadsöversikt</h3>
<div className="flex-1 space-y-0"> <div className="flex-1 space-y-0">

View File

@ -44,7 +44,7 @@ export const FDWideCardBlockComponent: React.FC<FDWideCardBlockProps> = ({
return ( return (
<section id={anchorId || undefined} className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}> <section id={anchorId || undefined} className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
<div className="max-w-[1200px] mx-auto px-6 md:px-8"> <div className="max-w-[1200px] mx-auto px-6 md:px-8">
<div className={`${card.bg} ${cardRadius} overflow-hidden flex flex-col lg:flex-row`}> <div className={`${card.bg} ${cardRadius} overflow-hidden flex flex-col min-[820px]:flex-row`}>
<div className="flex-1 flex flex-col justify-center gap-5 md:gap-6 px-8 md:px-14 lg:px-16 py-12 md:py-16"> <div className="flex-1 flex flex-col justify-center gap-5 md:gap-6 px-8 md:px-14 lg:px-16 py-12 md:py-16">
<h2 className={`font-joey-heavy text-fd-h1 leading-tight ${card.heading}`}> <h2 className={`font-joey-heavy text-fd-h1 leading-tight ${card.heading}`}>
{heading} {heading}