+
setOpen((prev) => !prev)}
+ aria-label="Country selector"
+ style={{
+ background: 'transparent',
+ border: 'none',
+ cursor: 'pointer',
+ padding: '6px',
+ borderRadius: '6px',
+ transition: 'background-color 0.15s ease',
+ lineHeight: 1,
+ display: 'flex',
+ alignItems: 'center',
+ }}
+ onMouseEnter={(e) => {
+ e.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.12)';
+ }}
+ onMouseLeave={(e) => {
+ e.currentTarget.style.backgroundColor = 'transparent';
+ }}
+ >
+
+
+
+ {(open || contentHeight > 0) && (
+ <>
+ {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
+
setOpen(false)}
+ style={{ position: 'fixed', inset: 0, zIndex: 999, cursor: 'default' }}
+ />
+
+
+ {countries.map((country, i) => (
+ handleCountryChange(country.id)}
+ style={{
+ display: 'flex',
+ alignItems: 'center',
+ width: '100%',
+ textAlign: 'left',
+ padding: '11px 16px',
+ borderRadius: '10px',
+ border: 'none',
+ background: 'transparent',
+ cursor: 'pointer',
+ fontSize: '14px',
+ fontFamily: typography.fontFamily.primary,
+ fontWeight:
+ countryId === country.id
+ ? typography.fontWeight.bold
+ : typography.fontWeight.semibold,
+ color: colors.primary[800],
+ transition: 'background-color 0.12s ease, color 0.12s ease, opacity 0.3s ease',
+ transitionDelay: visible ? `${i * 50}ms` : '0ms',
+ opacity: visible ? 1 : 0,
+ lineHeight: '1.3',
+ letterSpacing: '-0.01em',
+ }}
+ onMouseEnter={(e) => {
+ e.currentTarget.style.backgroundColor = colors.primary[500];
+ e.currentTarget.style.color = colors.text.inverse;
+ }}
+ onMouseLeave={(e) => {
+ e.currentTarget.style.backgroundColor = 'transparent';
+ e.currentTarget.style.color = colors.primary[800];
+ }}
+ >
+ {country.label}
+ {countryId === country.id && (
+ ✓
+ )}
+
+ ))}
+
+
+ >
+ )}
+
+ );
+}
diff --git a/src/components/homeHeader/DesktopNavigation.jsx b/src/components/homeHeader/DesktopNavigation.jsx
new file mode 100644
index 0000000..f8d1169
--- /dev/null
+++ b/src/components/homeHeader/DesktopNavigation.jsx
@@ -0,0 +1,13 @@
+'use client';
+
+import NavItem from './NavItem';
+
+export default function DesktopNavigation({ navItems }) {
+ return (
+
+ {navItems.map((item) => (
+
+ ))}
+
+ );
+}
diff --git a/src/components/homeHeader/HeaderActionButtons.jsx b/src/components/homeHeader/HeaderActionButtons.jsx
new file mode 100644
index 0000000..126c352
--- /dev/null
+++ b/src/components/homeHeader/HeaderActionButtons.jsx
@@ -0,0 +1,7 @@
+'use client';
+
+import CountrySelector from './CountrySelector';
+
+export default function HeaderActionButtons() {
+ return
;
+}
diff --git a/src/components/homeHeader/HeaderContent.jsx b/src/components/homeHeader/HeaderContent.jsx
new file mode 100644
index 0000000..260bfdc
--- /dev/null
+++ b/src/components/homeHeader/HeaderContent.jsx
@@ -0,0 +1,30 @@
+'use client';
+
+import DesktopNavigation from './DesktopNavigation';
+import HeaderActionButtons from './HeaderActionButtons';
+import HeaderLogo from './HeaderLogo';
+import MobileMenu from './MobileMenu';
+
+export default function HeaderContent({
+ opened,
+ onOpen,
+ onClose,
+ navItems,
+}) {
+ return (
+
+ );
+}
diff --git a/src/components/homeHeader/HeaderLogo.jsx b/src/components/homeHeader/HeaderLogo.jsx
new file mode 100644
index 0000000..fc1c078
--- /dev/null
+++ b/src/components/homeHeader/HeaderLogo.jsx
@@ -0,0 +1,26 @@
+'use client';
+
+import { spacing } from '@policyengine/design-system/tokens';
+const PolicyEngineLogo = '/us/api/assets/logos/policyengine/white.svg';
+
+const logoContainerStyles = {
+ display: 'flex',
+ alignItems: 'center',
+ cursor: 'pointer',
+};
+
+const logoImageStyles = {
+ height: '24px',
+ width: 'auto',
+ marginRight: 12,
+};
+
+export default function HeaderLogo() {
+ const logoImage =
;
+
+ return (
+
+ {logoImage}
+
+ );
+}
diff --git a/src/components/homeHeader/MobileMenu.jsx b/src/components/homeHeader/MobileMenu.jsx
new file mode 100644
index 0000000..72a0f76
--- /dev/null
+++ b/src/components/homeHeader/MobileMenu.jsx
@@ -0,0 +1,141 @@
+'use client';
+
+import { useEffect } from 'react';
+import { IconMenu2, IconX } from '@tabler/icons-react';
+import { colors, spacing, typography } from '@policyengine/design-system/tokens';
+import CountrySelector from './CountrySelector';
+
+export default function MobileMenu({ opened, onOpen, onClose, navItems }) {
+ // Lock body scroll when sheet is open
+ useEffect(() => {
+ if (opened) {
+ document.body.style.overflow = 'hidden';
+ } else {
+ document.body.style.overflow = '';
+ }
+ return () => {
+ document.body.style.overflow = '';
+ };
+ }, [opened]);
+
+ return (
+ <>
+ {/* Mobile Burger Menu with Country Selector */}
+
+
+
+
+
+
+
+ {/* Mobile Sheet — matches Radix Sheet side="right" */}
+ {opened && (
+ <>
+ {/* Overlay */}
+ {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
+
+ {/* Panel */}
+
+ {/* SheetHeader */}
+
+ Menu
+
+
+
+
+ {/* SheetContent nav items */}
+
+ {navItems.map((item) =>
+ item.hasDropdown && item.dropdownItems ? (
+ // Render dropdown as a section
+
+ ) : (
+ // Render regular link
+
+ {item.label}
+
+ )
+ )}
+
+
+ >
+ )}
+ >
+ );
+}
diff --git a/src/components/homeHeader/NavItem.jsx b/src/components/homeHeader/NavItem.jsx
new file mode 100644
index 0000000..f711bf3
--- /dev/null
+++ b/src/components/homeHeader/NavItem.jsx
@@ -0,0 +1,235 @@
+'use client';
+
+import { useCallback, useEffect, useRef, useState } from 'react';
+import { IconChevronDown } from '@tabler/icons-react';
+import { colors, typography } from '@policyengine/design-system/tokens';
+
+const navItemStyle = {
+ color: colors.text.inverse,
+ fontWeight: typography.fontWeight.medium,
+ fontSize: '15px',
+ fontFamily: typography.fontFamily.primary,
+ textDecoration: 'none',
+ padding: '6px 14px',
+ borderRadius: '6px',
+ transition: 'background-color 0.15s ease',
+ letterSpacing: '0.01em',
+};
+
+const hoverHandlers = {
+ onMouseEnter: (e) => {
+ e.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.12)';
+ },
+ onMouseLeave: (e) => {
+ e.currentTarget.style.backgroundColor = 'transparent';
+ },
+};
+
+/**
+ * Check if href is a relative path (internal) vs absolute URL (external).
+ */
+function isInternalHref(href) {
+ return !!href && href.startsWith('/');
+}
+
+/**
+ * Apple-style dropdown panel with smooth height reveal and content fade.
+ */
+function AppleDropdown({ items, open, onClose }) {
+ const contentRef = useRef(null);
+ const [contentHeight, setContentHeight] = useState(0);
+ const [visible, setVisible] = useState(false);
+
+ useEffect(() => {
+ if (open && contentRef.current) {
+ setContentHeight(contentRef.current.scrollHeight);
+ requestAnimationFrame(() => setVisible(true));
+ } else {
+ setVisible(false);
+ const timer = setTimeout(() => setContentHeight(0), 250);
+ return () => clearTimeout(timer);
+ }
+ }, [open]);
+
+ const handleSelect = useCallback(
+ (item) => {
+ onClose();
+ if (item.href) {
+ window.location.href = item.href;
+ } else if (item.onClick) {
+ item.onClick();
+ }
+ },
+ [onClose]
+ );
+
+ if (!open && contentHeight === 0) {
+ return null;
+ }
+
+ return (
+ <>
+ {/* Invisible click-away layer (no dim) — sits below the header's z-index */}
+ {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
+
+ {/* Dropdown panel */}
+
+
+ {items.map((item, i) => (
+ handleSelect(item)}
+ style={{
+ display: 'flex',
+ alignItems: 'center',
+ width: '100%',
+ textAlign: 'left',
+ padding: '11px 16px',
+ borderRadius: '10px',
+ border: 'none',
+ background: 'transparent',
+ cursor: 'pointer',
+ fontSize: '14px',
+ fontFamily: typography.fontFamily.primary,
+ fontWeight: typography.fontWeight.semibold,
+ color: colors.primary[800],
+ transition: 'background-color 0.12s ease, color 0.12s ease, opacity 0.3s ease',
+ transitionDelay: visible ? `${i * 50}ms` : '0ms',
+ opacity: visible ? 1 : 0,
+ lineHeight: '1.3',
+ letterSpacing: '-0.01em',
+ }}
+ onMouseEnter={(e) => {
+ e.currentTarget.style.backgroundColor = colors.primary[500];
+ e.currentTarget.style.color = colors.text.inverse;
+ }}
+ onMouseLeave={(e) => {
+ e.currentTarget.style.backgroundColor = 'transparent';
+ e.currentTarget.style.color = colors.primary[800];
+ }}
+ >
+ {item.label}
+
+ ))}
+
+
+ >
+ );
+}
+
+/**
+ * Reusable navigation item component.
+ * Can be either a simple link or a dropdown menu.
+ */
+export default function NavItem({ setup }) {
+ const { label, onClick, href, hasDropdown, dropdownItems } = setup;
+ const [dropdownOpen, setDropdownOpen] = useState(false);
+ const containerRef = useRef(null);
+
+ // Close on click outside
+ useEffect(() => {
+ if (!dropdownOpen) {
+ return;
+ }
+ function handleClick(e) {
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
+ setDropdownOpen(false);
+ }
+ }
+ document.addEventListener('mousedown', handleClick);
+ return () => document.removeEventListener('mousedown', handleClick);
+ }, [dropdownOpen]);
+
+ // Close on Escape
+ useEffect(() => {
+ if (!dropdownOpen) {
+ return;
+ }
+ function handleKey(e) {
+ if (e.key === 'Escape') {
+ setDropdownOpen(false);
+ }
+ }
+ document.addEventListener('keydown', handleKey);
+ return () => document.removeEventListener('keydown', handleKey);
+ }, [dropdownOpen]);
+
+ if (hasDropdown && dropdownItems) {
+ return (
+
+
{
+ onClick?.();
+ setDropdownOpen((prev) => !prev);
+ }}
+ style={{
+ ...navItemStyle,
+ background: 'transparent',
+ border: 'none',
+ cursor: 'pointer',
+ display: 'flex',
+ alignItems: 'center',
+ gap: '4px',
+ }}
+ {...hoverHandlers}
+ >
+ {label}
+
+
+
setDropdownOpen(false)}
+ />
+
+ );
+ }
+
+ // Absolute URLs use standard anchor tag
+ return (
+
+ {label}
+
+ );
+}