MMade with MythMind AI );\nexport const img = (id: string, width = 1200) =\u003e `https://images.unsplash.com/${id}?w=${width}\u0026auto=format\u0026fit=crop\u0026q=80`;\n","src/lib/gsap.ts":"import { gsap } from 'gsap';\nimport { ScrollTrigger } from 'gsap/ScrollTrigger';\nimport { Flip } from 'gsap/Flip';\nimport { Observer } from 'gsap/Observer';\n\ngsap.registerPlugin(ScrollTrigger, Flip, Observer);\nexport { gsap, ScrollTrigger, Flip, Observer };\n","src/lib/lenis.ts":"import Lenis from 'lenis';\nimport { ScrollTrigger } from './gsap.ts';\n\nexport const startLenis = (reduced: boolean) =\u003e {\n if (reduced) return () =\u003e {};\n const lenis = new Lenis({ lerp: 0.09, smoothWheel: true });\n let frame = 0;\n const raf = (time: number) =\u003e { lenis.raf(time); ScrollTrigger.update(); frame = requestAnimationFrame(raf); };\n frame = requestAnimationFrame(raf);\n return () =\u003e { cancelAnimationFrame(frame); lenis.destroy(); };\n};\n","src/hooks/useTheme.ts":"import { useEffect, useState } from 'react';\n\nexport const useTheme = () =\u003e {\n const [theme, setTheme] = useState\u003c'light' | 'dark'\u003e(() =\u003e (localStorage.getItem('nepal-theme') as 'light' | 'dark') || (matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'));\n useEffect(() =\u003e { document.documentElement.dataset.theme = theme; localStorage.setItem('nepal-theme', theme); }, [theme]);\n return { theme, setTheme };\n};\n","src/hooks/useReducedMotion.ts":"import { useEffect, useState } from 'react';\n\nexport const useReducedMotion = () =\u003e {\n const [reduced, setReduced] = useState(matchMedia('(prefers-reduced-motion: reduce)').matches);\n useEffect(() =\u003e { const query = matchMedia('(prefers-reduced-motion: reduce)'); const update = () =\u003e setReduced(query.matches); query.addEventListener('change', update); return () =\u003e query.removeEventListener('change', update); }, []);\n return reduced;\n};\n","src/data/nepal.ts":"import { img } from '../lib/utils.ts';\n\nexport interface Experience { slug:string; name:string; location:string; season:string; price:string; tags:string[]; difficulty:string; image:string; description:string; }\nexport const experiences: Experience[] = [\n { slug:'everest-base-camp', name:'Everest Base Camp Trek', location:'Khumbu', season:'Mar–May / Oct–Nov', price:'USD 1,450', tags:['classic','high altitude','Sherpa'], difficulty:'Demanding', image:img('photo-1544735716-392fe2489ffa'), description:'Classic two-week route through Sherpa villages, swinging bridges, monasteries and glacial valleys beneath the world’s highest peaks. Acclimatization in Namche Bazaar brings the journey into local rhythm before Kala Patthar opens views of Ama Dablam, Lhotse and Everest.' },\n { slug:'annapurna-circuit', name:'Annapurna Circuit Passage', location:'Annapurna', season:'Oct–Nov / Apr', price:'USD 1,250', tags:['classic','cultural','pass'], difficulty:'Challenging', image:img('photo-1519681393784-d120267933ba'), description:'A dramatic crossing from subtropical river valleys to Thorong La high pass. Languages, food, architecture and landscapes shift every few days, linking tea houses and apple orchards with Buddhist villages and enormous mountain amphitheaters.' },\n { slug:'kathmandu-heritage', name:'Kathmandu Valley Heritage Walk', location:'Kathmandu', season:'Year-round', price:'USD 85', tags:['culture','city','Newar'], difficulty:'Easy', image:img('photo-1605649487212-47bdab064df7'), description:'A guided day through courtyards, stupas, carved windows and temple squares. Designed for travelers seeking context beyond monuments, it connects Newar craft, Buddhist and Hindu practice, street food and the continuing work of restoration.' },\n { slug:'chitwan-rhino', name:'Chitwan River \u0026 Rhino Safari', location:'Terai', season:'Oct–Mar', price:'USD 320', tags:['wildlife','beginner','river'], difficulty:'Easy', image:img('photo-1535338454770-8be927b5a00b'), description:'Explore sal forest, grassland and river channels in Nepal’s subtropical south. Canoe rides, naturalist walks and golden-hour observation focus on one-horned rhinos, gharials, birdlife and respectful encounters with Tharu culture.' },\n { slug:'upper-mustang', name:'Upper Mustang Walled Kingdom Route', location:'Mustang', season:'May–Oct', price:'USD 2,250', tags:['remote','high altitude','culture'], difficulty:'Demanding', image:img('photo-1500534623283-312aade485b7'), description:'A high-desert journey through wind-carved cliffs, cave monasteries and whitewashed settlements. Restricted-area permits make this route more considered, while ochre canyons, prayer flags and Lo Manthang reveal a distinct Tibetan-influenced world.' },\n { slug:'lumbini-pilgrimage', name:'Lumbini Sacred Garden Pilgrimage', location:'Lumbini', season:'Nov–Feb', price:'USD 160', tags:['culture','quiet','pilgrimage'], difficulty:'Easy', image:img('photo-1564399579883-451a5d44ec08'), description:'A contemplative visit to the birthplace of Siddhartha Gautama. Time unfolds between the Maya Devi Temple, Ashokan Pillar, quiet gardens and monasteries built by Buddhist communities across the world.' },\n { slug:'pokhara-slow-days', name:'Pokhara Lakeside Slow Days', location:'Pokhara', season:'Sep–May', price:'USD 70/day', tags:['lake','beginner','food'], difficulty:'Easy', image:img('photo-1589884629108-3193400c7cc9'), description:'Lake reflections, cafés, cave shrines and Sarangkot sunrise make Pokhara both a recovery stop after trekking and a gentle introduction to the Annapurna range. Add a boat ride, an easy ridge walk or simply a slower morning.' },\n { slug:'langtang-renewal', name:'Langtang Valley Renewal Trek', location:'Langtang', season:'Mar–May / Oct', price:'USD 780', tags:['classic','Tamang','trek'], difficulty:'Moderate', image:img('photo-1464278533981-50106e6176b1'), description:'A shorter Himalayan trek with deep resonance after earthquake recovery. Forests, yak pastures, Tamang villages and broad alpine valleys lead toward Kyanjin Gompa, where cheese houses, glaciers and panorama feel intimate rather than distant.' },\n { slug:'tihar-lights', name:'Tihar Festival of Lights', location:'Nationwide', season:'Oct/Nov', price:'USD 40/day', tags:['festival','culture','seasonal'], difficulty:'Easy', image:img('photo-1518105779142-d975f22f1b0a'), description:'A luminous five-day season honoring crows, dogs, cows, siblings, wealth and household blessings. Oil lamps, rangoli, marigolds, sweets and music bring neighborhoods alive; visit as a respectful guest, not for a staged spectacle.' },\n { slug:'bhaktapur-courtyards', name:'Bhaktapur Clay, Brick \u0026 Courtyards', location:'Bhaktapur', season:'Year-round', price:'USD 95', tags:['craft','city','Newar'], difficulty:'Easy', image:img('photo-1548013146-72479768bada'), description:'A textured day among brick lanes, pottery squares, carved balconies and royal courtyards. Bhaktapur rewards slow attention: artisans at wheels, temple bells, drying grain and layered histories visible in rooflines and thresholds.' },\n { slug:'rara-lake', name:'Rara Lake Far West Escape', location:'Karnali', season:'Apr–Jun / Sep–Oct', price:'USD 1,650', tags:['remote','lake','nature'], difficulty:'Moderate', image:img('photo-1439853949127-fa647821eba0'), description:'A remote journey to Nepal’s largest lake, held by pine forests, alpine meadows and quiet ridges. Reaching Rara takes patience; the return is solitude, changing blue water and a lesser-seen side of the country.' },\n { slug:'ilam-tea-hills', name:'Ilam Tea Hills \u0026 Mist Roads', location:'Eastern Nepal', season:'Oct–Apr', price:'USD 240', tags:['tea','slow','cultural'], difficulty:'Easy', image:img('photo-1545048702-79362596cdc9'), description:'Rolling tea gardens, cool mornings, cardamom farms and quiet hill towns define Ilam. Ideal for travelers drawn to agricultural landscapes, slow travel and regional flavor, with plantation walks and careful local tea tastings.' }\n];\n\nexport const regions = [\n ['Kathmandu Valley','Courtyards, stupas and living Newar urban culture','photo-1605649487212-47bdab064df7'], ['Everest Region','Sherpa homelands, glaciers and high passes','photo-1544735716-392fe2489ffa'], ['Annapurna','River valleys, villages and broad mountain walls','photo-1519681393784-d120267933ba'], ['Mustang','Wind, ochre cliffs and walled settlements','photo-1500534623283-312aade485b7'], ['Chitwan / Terai','Grassland, river and one-horned rhino habitat','photo-1535338454770-8be927b5a00b'], ['Lumbini','Sacred gardens and transnational monasteries','photo-1564399579883-451a5d44ec08'], ['Langtang','Tamang villages and alpine valleys','photo-1464278533981-50106e6176b1'], ['Far West','Lake country, long roads and quieter trails','photo-1439853949127-fa647821eba0']\n].map(([name,copy,image]) =\u003e ({ name, copy, image:img(image) }));\n\nexport const festivals = ['Losar · Feb / Mar','Holi · Mar','Bisket Jatra · Apr','Indra Jatra · Sep','Dashain · Oct','Tihar · Oct / Nov','Mani Rimdu · Nov'];\n","src/components/ui/primitives.tsx":"import React, { useEffect, useRef } from 'react';\nimport { cn } from '../../lib/utils.ts';\nimport { X } from 'lucide-react';\n\ninterface ButtonProps extends React.ButtonHTMLAttributes\u003cHTMLButtonElement\u003e { variant?: 'primary'|'secondary'|'ghost'; size?: 'sm'|'md'|'lg'; }\nexport const Button = ({ variant='primary', size='md', className, ...props }: ButtonProps) =\u003e \u003cbutton className={cn('inline-flex items-center justify-center gap-2 rounded-full font-bold transition duration-200 focus-visible:ring-2 focus-visible:ring-[var(--brand-500)] disabled:opacity-50', variant === 'primary' \u0026\u0026 'bg-[var(--brand-500)] text-[var(--ink-inverse)] shadow-[var(--shadow-brand)] hover:-translate-y-0.5 hover:bg-[var(--brand-600)]', variant === 'secondary' \u0026\u0026 'border border-[var(--border-strong)] bg-[var(--surface)] text-[var(--ink)] hover:-translate-y-0.5', variant === 'ghost' \u0026\u0026 'text-[var(--ink)] hover:bg-[var(--surface)]', size === 'sm' \u0026\u0026 'px-3 py-2 text-xs', size === 'md' \u0026\u0026 'px-5 py-3 text-sm', size === 'lg' \u0026\u0026 'px-7 py-4 text-sm', className)} {...props} /\u003e;\n\nexport const Badge = ({ children }: { children: React.ReactNode }) =\u003e \u003cspan className=\"rounded-full border border-[var(--border)] px-2.5 py-1 font-mono text-[10px] uppercase tracking-wider text-[var(--ink-2)]\"\u003e{children}\u003c/span\u003e;\nexport const Card = ({ children, className }: { children: React.ReactNode; className?: string }) =\u003e \u003carticle className={cn('overflow-hidden rounded-[var(--r-lg)] border border-[var(--border)] bg-[var(--surface)] shadow-[var(--shadow)] transition duration-300 hover:-translate-y-1 hover:shadow-[var(--shadow-lg)]', className)}\u003e{children}\u003c/article\u003e;\nexport const Skeleton = ({ className='' }: { className?:string }) =\u003e \u003cdiv className={cn('animate-pulse rounded bg-[var(--surface-3)]', className)} /\u003e;\n\nexport const Modal = ({ open, onClose, title, children }: { open:boolean; onClose:()=\u003evoid; title:string; children:React.ReactNode }) =\u003e {\n const ref = useRef\u003cHTMLDivElement\u003e(null);\n useEffect(() =\u003e { const key = (e:KeyboardEvent) =\u003e { if(e.key === 'Escape') onClose(); }; if(open) { document.addEventListener('keydown',key); ref.current?.focus(); } return () =\u003e document.removeEventListener('keydown',key); }, [open,onClose]);\n if (!open) return null;\n return \u003cdiv className=\"fixed inset-0 z-[90] grid place-items-center bg-black/55 p-4 backdrop-blur-sm\" onMouseDown={onClose}\u003e\u003cdiv ref={ref} tabIndex={-1} role=\"dialog\" aria-modal=\"true\" aria-label={title} className=\"max-h-[90vh] w-full max-w-xl overflow-auto rounded-[var(--r-xl)] bg-[var(--bg)] p-7 shadow-[var(--shadow-xl)]\" onMouseDown={e=\u003ee.stopPropagation()}\u003e\u003cdiv className=\"mb-5 flex items-center justify-between\"\u003e\u003ch2 className=\"display text-3xl\"\u003e{title}\u003c/h2\u003e\u003cbutton aria-label=\"Close dialog\" onClick={onClose}\u003e\u003cX /\u003e\u003c/button\u003e\u003c/div\u003e{children}\u003c/div\u003e\u003c/div\u003e;\n};\n\nexport const EmptyState = ({ label='No route matches this altitude yet' }: { label?:string }) =\u003e \u003cdiv className=\"rounded-[var(--r-lg)] border border-dashed border-[var(--border-strong)] p-12 text-center\"\u003e\u003cp className=\"display text-3xl\"\u003e{label}\u003c/p\u003e\u003cp className=\"mt-3 text-[var(--ink-muted)]\"\u003eTry another filter or expand the season.\u003c/p\u003e\u003c/div\u003e;\nexport const ErrorState = ({ retry }: { retry:()=\u003evoid }) =\u003e \u003cdiv className=\"rounded-[var(--r-lg)] border border-[var(--brand-500)] bg-[var(--surface)] p-8\"\u003e\u003cp className=\"font-bold\"\u003eThe field notes could not be opened.\u003c/p\u003e\u003cButton className=\"mt-4\" size=\"sm\" onClick={retry}\u003eTry again\u003c/Button\u003e\u003c/div\u003e;\n","src/components/motion/Motion.tsx":"import React, { useEffect, useRef } from 'react';\nimport { gsap } from '../../lib/gsap.ts';\nimport { useReducedMotion } from '../../hooks/useReducedMotion.ts';\n\nexport const CursorFollower = () =\u003e {\n const reduced = useReducedMotion();\n const dot = useRef\u003cHTMLDivElement\u003e(null);\n useEffect(() =\u003e { if(reduced || matchMedia('(pointer: coarse)').matches) return; const move=(e:MouseEvent)=\u003egsap.to(dot.current,{x:e.clientX,y:e.clientY,duration:.35,ease:'power3.out'}); addEventListener('mousemove',move); return()=\u003eremoveEventListener('mousemove',move); },[reduced]);\n return \u003cdiv ref={dot} className=\"pointer-events-none fixed left-[-10px] top-[-10px] z-[100] hidden h-5 w-5 rounded-full border border-[var(--brand-500)] mix-blend-multiply md:block\" /\u003e;\n};\n\nexport const MagneticButton = ({ children }: { children:React.ReactNode }) =\u003e {\n const ref = useRef\u003cHTMLSpanElement\u003e(null); const reduced = useReducedMotion();\n const move=(e:React.MouseEvent) =\u003e { if(reduced) return; const r=ref.current!.getBoundingClientRect(); gsap.to(ref.current,{x:(e.clientX-r.left-r.width/2)*.13,y:(e.clientY-r.top-r.height/2)*.13,duration:.25}); };\n return \u003cspan ref={ref} onMouseMove={move} onMouseLeave={()=\u003egsap.to(ref.current,{x:0,y:0,duration:.45})} className=\"inline-block\"\u003e{children}\u003c/span\u003e;\n};\n\nexport const Marquee = ({ items }: { items:string[] }) =\u003e \u003cdiv className=\"overflow-hidden border-y border-[var(--border)] py-4\"\u003e\u003cdiv className=\"flex w-max animate-[marquee_35s_linear_infinite] gap-10 whitespace-nowrap font-mono text-xs uppercase tracking-[.18em] text-[var(--brand-700)]\"\u003e{[...items,...items].map((item,i)=\u003e\u003cspan key={i}\u003e✦ {item}\u003c/span\u003e)}\u003c/div\u003e\u003c/div\u003e;\n","src/components/layout/Layout.tsx":"import React, { useEffect, useState } from 'react';\nimport { Menu, Moon, Sun, X } from 'lucide-react';\nimport { useTheme } from '../../hooks/useTheme.ts';\nimport { Button } from '../ui/primitives.tsx';\n\nconst links = [['Atlas','#/'],['Regions','#/regions'],['Treks','#/treks'],['Culture','#/culture'],['Food \u0026 Crafts','#/food-crafts'],['Guide','#/guide'],['Stories','#/stories'],['Plan','#/plan']];\nexport const Layout = ({ children }: { children:React.ReactNode }) =\u003e {\n const { theme,setTheme } = useTheme(); const [open,setOpen]=useState(false);\n useEffect(()=\u003e{ const key=(e:KeyboardEvent)=\u003ee.key==='Escape'\u0026\u0026setOpen(false); addEventListener('keydown',key); return()=\u003eremoveEventListener('keydown',key); },[]);\n return \u003c\u003e\u003ca href=\"#content\" className=\"sr-only focus:not-sr-only focus:absolute focus:z-[120] focus:m-4 focus:bg-[var(--brand-400)] focus:p-3\"\u003eSkip to content\u003c/a\u003e\u003cheader className=\"sticky top-0 z-50 border-b border-[var(--border)] bg-[color-mix(in_oklab,var(--bg)_88%,transparent)] backdrop-blur-xl\"\u003e\u003cdiv className=\"mx-auto flex max-w-[1728px] items-center justify-between px-5 py-3 md:px-9\"\u003e\u003ca href=\"#/\" className=\"display text-2xl\"\u003eनेपाल \u003cspan className=\"font-sans text-xs font-bold uppercase tracking-[.18em]\"\u003eAtlas\u003c/span\u003e\u003c/a\u003e\u003cnav className=\"hidden items-center gap-5 lg:flex\"\u003e{links.map(([n,h])=\u003e\u003ca className=\"text-xs font-bold hover:text-[var(--brand-500)]\" href={h} key={h}\u003e{n}\u003c/a\u003e)}\u003c/nav\u003e\u003cdiv className=\"flex gap-2\"\u003e\u003cbutton aria-label=\"Toggle color theme\" className=\"rounded-full p-2 hover:bg-[var(--surface)]\" onClick={()=\u003esetTheme(theme==='light'?'dark':'light')}\u003e{theme==='light'?\u003cMoon size={17}/\u003e:\u003cSun size={17}/\u003e}\u003c/button\u003e\u003cbutton aria-label=\"Open navigation\" className=\"p-2 lg:hidden\" onClick={()=\u003esetOpen(true)}\u003e\u003cMenu /\u003e\u003c/button\u003e\u003c/div\u003e\u003c/div\u003e\u003c/header\u003e{open\u0026\u0026\u003cdiv className=\"fixed inset-0 z-[80] bg-[var(--bg)] p-6 lg:hidden\"\u003e\u003cdiv className=\"flex justify-between\"\u003e\u003cspan className=\"display text-3xl\"\u003eField index\u003c/span\u003e\u003cbutton aria-label=\"Close navigation\" onClick={()=\u003esetOpen(false)}\u003e\u003cX /\u003e\u003c/button\u003e\u003c/div\u003e\u003cnav className=\"mt-14 flex flex-col gap-5\"\u003e{links.map(([n,h],i)=\u003e\u003ca onClick={()=\u003esetOpen(false)} className=\"display border-b border-[var(--border)] pb-4 text-4xl\" href={h} key={h}\u003e0{i+1} · {n}\u003c/a\u003e)}\u003c/nav\u003e\u003c/div\u003e}\u003cmain id=\"content\"\u003e{children}\u003c/main\u003e\u003cfooter className=\"border-t border-[var(--border)] bg-[var(--brand-900)] px-5 py-16 text-[var(--brand-50)] md:px-9\"\u003e\u003cdiv className=\"mx-auto grid max-w-[1728px] gap-10 md:grid-cols-4\"\u003e\u003cdiv\u003e\u003cp className=\"display text-4xl\"\u003eThe living\u003cbr/\u003eHimalaya.\u003c/p\u003e\u003cp className=\"mt-5 max-w-xs text-sm text-[var(--brand-100)]\"\u003eA field guide for curious, considerate journeys through Nepal.\u003c/p\u003e\u003c/div\u003e\u003cdiv\u003e\u003cp className=\"eyebrow text-[var(--brand-400)]\"\u003eExplore\u003c/p\u003e\u003cdiv className=\"mt-4 grid gap-2 text-sm\"\u003e{links.slice(1,5).map(([n,h])=\u003e\u003ca href={h} key={h}\u003e{n}\u003c/a\u003e)}\u003c/div\u003e\u003c/div\u003e\u003cdiv\u003e\u003cp className=\"eyebrow text-[var(--brand-400)]\"\u003eTravel with care\u003c/p\u003e\u003cp className=\"mt-4 text-sm text-[var(--brand-100)]\"\u003eCheck current official requirements, hire local expertise, and let places set their own pace.\u003c/p\u003e\u003c/div\u003e\u003cdiv\u003e\u003cp className=\"eyebrow text-[var(--brand-400)]\"\u003eField post\u003c/p\u003e\u003cform onSubmit={e=\u003e{e.preventDefault(); alert('Thank you — field notes are on their way.');}} className=\"mt-4 flex gap-2\"\u003e\u003cinput aria-label=\"Email address\" required type=\"email\" placeholder=\"Your email\" className=\"min-w-0 rounded-full border-0 bg-white px-4 py-2 text-sm text-black\"/\u003e\u003cButton size=\"sm\"\u003eJoin\u003c/Button\u003e\u003c/form\u003e\u003c/div\u003e\u003c/div\u003e\u003c/footer\u003e\u003c/\u003e;\n};\n","src/components/sections/AtlasSections.tsx":"import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { Pause, Play, ArrowUpRight, Heart } from 'lucide-react';\nimport { gsap, ScrollTrigger, Flip, Observer } from '../../lib/gsap.ts';\nimport { experiences, festivals, regions, Experience } from '../../data/nepal.ts';\nimport { Badge, Button, Card, Skeleton } from '../ui/primitives.tsx';\nimport { MagneticButton, Marquee } from '../motion/Motion.tsx';\nimport { useReducedMotion } from '../../hooks/useReducedMotion.ts';\n\nexport const Hero = ({ title='Nepal:', subtitle='Where the Earth Rises.', image='https://images.unsplash.com/photo-1544735716-392fe2489ffa?w=1800\u0026auto=format\u0026fit=crop\u0026q=80' }: { title?:string; subtitle?:string; image?:string }) =\u003e {\n const ref=useRef\u003cHTMLElement\u003e(null); const video=useRef\u003cHTMLVideoElement\u003e(null); const [paused,setPaused]=useState(false); const reduced=useReducedMotion();\n useLayoutEffect(()=\u003e{ if(reduced) return; const ctx=gsap.context(()=\u003e{ const tl=gsap.timeline(); tl.from('.curtain',{yPercent:0,duration:1.1,ease:'power4.inOut'}).from('.hero-word',{y:80,opacity:0,filter:'blur(12px)',stagger:.14,duration:.9,ease:'power4.out'},'-=.45').from('.hero-meta',{opacity:0,y:15,stagger:.1},'-=.4'); gsap.to('.hero-route',{xPercent:8,yPercent:-4,scrollTrigger:{trigger:ref.current,start:'top top',end:'bottom top',scrub:1}}); },ref); return()=\u003ectx.revert(); },[reduced]);\n const toggle=()=\u003e{ if(video.current?.paused){video.current.play();setPaused(false);}else{video.current?.pause();setPaused(true);} };\n return \u003csection ref={ref} className=\"relative isolate min-h-[82vh] overflow-hidden bg-[var(--brand-900)] text-[var(--brand-50)]\"\u003e\u003cvideo ref={video} autoPlay={!reduced} muted loop playsInline preload=\"metadata\" poster={image} className=\"absolute inset-0 h-full w-full object-cover opacity-55\"\u003e\u003csource src=\"https://videos.pexels.com/video-files/3129595/3129595-hd_1920_1080_25fps.mp4\" type=\"video/mp4\" /\u003e\u003c/video\u003e\u003cdiv className=\"absolute inset-0 bg-gradient-to-t from-[#15191ddd] via-[#15191d55] to-[#15191d22]\"/\u003e\u003cdiv className=\"hero-route absolute right-[8%] top-[22%] h-[42%] w-[48%] rounded-full border border-dashed border-[var(--brand-400)] opacity-70\"/\u003e\u003cdiv className=\"relative mx-auto flex min-h-[82vh] max-w-[1728px] flex-col justify-end px-5 pb-12 md:px-9 md:pb-20\"\u003e\u003cp className=\"hero-meta font-mono text-[10px] tracking-[.2em] text-[var(--brand-400)]\"\u003e27.7172° N / 85.3240° E · ALTITUDE VARIABLE\u003c/p\u003e\u003ch1 className=\"mt-5 max-w-6xl overflow-hidden display text-[clamp(58px,10vw,160px)]\"\u003e\u003cspan className=\"hero-word inline-block\"\u003e{title}\u003c/span\u003e\u003cbr/\u003e\u003cspan className=\"hero-word inline-block italic text-[var(--brand-100)]\"\u003e{subtitle}\u003c/span\u003e\u003c/h1\u003e\u003cdiv className=\"hero-meta mt-8 flex flex-wrap items-center gap-4\"\u003e\u003cMagneticButton\u003e\u003ca href=\"#/regions\"\u003e\u003cButton size=\"lg\"\u003eBegin the atlas \u003cArrowUpRight size={17}/\u003e\u003c/Button\u003e\u003c/a\u003e\u003c/MagneticButton\u003e\u003ca className=\"rounded-full px-4 py-3 text-sm font-bold hover:bg-white/10\" href=\"#/plan\"\u003ePlan with context\u003c/a\u003e\u003c/div\u003e\u003cbutton aria-label={paused?'Play hero video':'Pause hero video'} onClick={toggle} className=\"hero-meta absolute bottom-8 right-5 rounded-full border border-white/40 p-3 md:right-9\"\u003e{paused?\u003cPlay size={15}/\u003e:\u003cPause size={15}/\u003e}\u003c/button\u003e\u003c/div\u003e\u003cdiv className=\"curtain absolute inset-0 z-10 origin-top bg-[var(--brand-100)]\"/\u003e\u003c/section\u003e;\n};\n\nexport const ExperienceCard = ({ item, favorite }: { item:Experience; favorite?:boolean }) =\u003e \u003cCard className=\"group\"\u003e\u003cdiv className=\"relative h-64 overflow-hidden\"\u003e\u003cimg width=\"900\" height=\"700\" loading=\"lazy\" src={item.image} alt={item.name} className=\"h-[115%] w-full object-cover transition duration-700 group-hover:scale-105\"/\u003e\u003cbutton aria-label=\"Save experience\" className=\"absolute right-3 top-3 rounded-full bg-[var(--bg)] p-2 text-[var(--brand-500)]\"\u003e\u003cHeart size={16} fill={favorite?'currentColor':'none'}/\u003e\u003c/button\u003e\u003c/div\u003e\u003cdiv className=\"p-5\"\u003e\u003cdiv className=\"flex justify-between gap-3\"\u003e\u003cp className=\"eyebrow\"\u003e{item.location}\u003c/p\u003e\u003cp className=\"font-mono text-[10px]\"\u003e{item.price}\u003c/p\u003e\u003c/div\u003e\u003ch3 className=\"display mt-3 text-3xl\"\u003e{item.name}\u003c/h3\u003e\u003cp className=\"mt-3 text-sm text-[var(--ink-2)]\"\u003e{item.description}\u003c/p\u003e\u003cdiv className=\"mt-5 flex flex-wrap gap-2\"\u003e{item.tags.map(x=\u003e\u003cBadge key={x}\u003e{x}\u003c/Badge\u003e)}\u003c/div\u003e\u003ca href={`#/detail/${item.slug}`} className=\"mt-5 inline-block text-sm font-bold text-[var(--brand-500)]\"\u003eOpen field note →\u003c/a\u003e\u003c/div\u003e\u003c/Card\u003e;\n\nexport const Stats = () =\u003e { const ref=useRef\u003cHTMLDivElement\u003e(null); const reduced=useReducedMotion(); useEffect(()=\u003e{if(reduced)return; const ctx=gsap.context(()=\u003e{gsap.utils.toArray\u003cHTMLElement\u003e('.stat-num').forEach(el=\u003e{const n=Number(el.dataset.n); const o={n:0}; gsap.to(o,{n,duration:2,scrollTrigger:{trigger:el,start:'top 80%'},onUpdate:()=\u003eel.textContent=Math.round(o.n).toString()});});},ref);return()=\u003ectx.revert();},[reduced]); return \u003cdiv ref={ref} className=\"grid border-y border-[var(--border)] sm:grid-cols-4\"\u003e{[[8,'of the world’s 14 highest peaks'],[123,'languages and mother tongues'],[10,'UNESCO World Heritage sites'],[6,'seasons in local rhythms']].map(([n,l])=\u003e\u003cdiv className=\"border-b border-[var(--border)] p-7 last:border-0 sm:border-b-0 sm:border-r sm:last:border-0\" key={String(l)}\u003e\u003cp data-n={n} className=\"stat-num display text-5xl\"\u003e0\u003c/p\u003e\u003cp className=\"mt-2 text-xs text-[var(--ink-muted)]\"\u003e{l}\u003c/p\u003e\u003c/div\u003e)}\u003c/div\u003e };\n\nexport const AltitudeScene = () =\u003e { const ref=useRef\u003cHTMLElement\u003e(null); const reduced=useReducedMotion(); useLayoutEffect(()=\u003e{if(reduced)return; const ctx=gsap.context(()=\u003e{gsap.to('.peak-line',{strokeDashoffset:0,scrollTrigger:{trigger:ref.current,start:'top top',end:'+=1100',scrub:1,pin:true}});gsap.fromTo('.alt-label',{opacity:.1},{opacity:1,stagger:.4,scrollTrigger:{trigger:ref.current,start:'top 45%',end:'bottom 60%',scrub:1}});},ref);return()=\u003ectx.revert();},[reduced]);return \u003csection ref={ref} className=\"overflow-hidden bg-[var(--brand-900)] px-5 py-20 text-[var(--brand-50)] md:px-9\"\u003e\u003cdiv className=\"mx-auto max-w-[1400px]\"\u003e\u003cp className=\"eyebrow text-[var(--brand-400)]\"\u003eA vertical country\u003c/p\u003e\u003ch2 className=\"display mt-3 max-w-3xl text-5xl md:text-7xl\"\u003eFrom humid grassland to the thin, bright air of the high Himalaya.\u003c/h2\u003e\u003csvg viewBox=\"0 0 1200 430\" className=\"mt-16 w-full overflow-visible\"\u003e\u003cpath className=\"peak-line\" d=\"M0 385 L140 370 L250 320 L360 345 L460 245 L560 300 L690 135 L790 245 L930 38 L1040 215 L1200 120\" fill=\"none\" stroke=\"#E8A11A\" strokeWidth=\"5\" strokeDasharray=\"1600\" strokeDashoffset=\"1600\"/\u003e\u003cpath d=\"M0 385 L140 370 L250 320 L360 345 L460 245 L560 300 L690 135 L790 245 L930 38 L1040 215 L1200 120 V430 H0Z\" fill=\"#2f5d50\" opacity=\".55\"/\u003e\u003ctext x=\"20\" y=\"415\" className=\"alt-label\" fill=\"#E9DDC7\"\u003eTERAI · 60M\u003c/text\u003e\u003ctext x=\"410\" y=\"225\" className=\"alt-label\" fill=\"#E9DDC7\"\u003eKATHMANDU · 1,400M\u003c/text\u003e\u003ctext x=\"850\" y=\"30\" className=\"alt-label\" fill=\"#E8A11A\"\u003eEVEREST · 8,849M\u003c/text\u003e\u003c/svg\u003e\u003c/div\u003e\u003c/section\u003e };\n\nexport const TrekStrip = () =\u003e { const ref=useRef\u003cHTMLElement\u003e(null); const reduced=useReducedMotion(); useLayoutEffect(()=\u003e{if(reduced)return; const ctx=gsap.context(()=\u003e{const rail=ref.current?.querySelector('.trek-rail') as HTMLElement; gsap.to(rail,{x:()=\u003e-(rail.scrollWidth-innerWidth+80),ease:'none',scrollTrigger:{trigger:ref.current,start:'top top',end:()=\u003e`+=${rail.scrollWidth}`,scrub:1,pin:true}});},ref);return()=\u003ectx.revert();},[reduced]);return \u003csection ref={ref} className=\"overflow-hidden bg-[var(--surface-2)] py-20\"\u003e\u003cdiv className=\"px-5 md:px-9\"\u003e\u003cp className=\"eyebrow\"\u003eRoutes in motion\u003c/p\u003e\u003ch2 className=\"display mt-2 text-5xl\"\u003eWalk the contours.\u003c/h2\u003e\u003c/div\u003e\u003cdiv className=\"trek-rail mt-10 flex w-max gap-5 px-5 md:px-9\"\u003e{experiences.filter(x=\u003ex.tags.includes('classic')||x.tags.includes('remote')||x.tags.includes('trek')).slice(0,5).map(x=\u003e\u003cdiv className=\"w-[310px]\" key={x.slug}\u003e\u003cExperienceCard item={x}/\u003e\u003c/div\u003e)}\u003c/div\u003e\u003c/section\u003e };\n\nexport const RegionTerrain = () =\u003e { const [active,setActive]=useState(0); const ref=useRef\u003cHTMLDivElement\u003e(null); useEffect(()=\u003e{const ctx=gsap.context(()=\u003eObserver.create({target:ref.current,type:'wheel,touch',onDown:()=\u003esetActive(v=\u003e(v+1)%regions.length),onUp:()=\u003esetActive(v=\u003e(v+regions.length-1)%regions.length)}),ref);return()=\u003ectx.revert();},[]); const r=regions[active]; return \u003csection className=\"paper px-5 py-20 md:px-9\"\u003e\u003cdiv className=\"mx-auto grid max-w-[1450px] gap-10 lg:grid-cols-[.8fr_1.2fr]\"\u003e\u003cdiv\u003e\u003cp className=\"eyebrow\"\u003eTerrain index\u003c/p\u003e\u003ch2 className=\"display mt-3 text-5xl\"\u003eA country in layers.\u003c/h2\u003e\u003cp className=\"mt-5 max-w-md text-[var(--ink-2)]\"\u003eScroll, drag, or choose a name to move across this illustrated relief. Route lines speak to distance, not conquest.\u003c/p\u003e\u003cdiv className=\"mt-8 grid grid-cols-2 gap-2\"\u003e{regions.map((x,i)=\u003e\u003cbutton onClick={()=\u003esetActive(i)} className={`border p-3 text-left text-xs font-bold ${i===active?'border-[var(--brand-500)] bg-[var(--brand-500)] text-white':'border-[var(--border)]'}`} key={x.name}\u003e{x.name}\u003c/button\u003e)}\u003c/div\u003e\u003c/div\u003e\u003cdiv ref={ref} className=\"relative min-h-[460px] overflow-hidden rounded-[var(--r-xl)] bg-[var(--brand-800)] shadow-[var(--shadow-xl)]\"\u003e\u003cimg width=\"1200\" height=\"900\" loading=\"lazy\" src={r.image} alt={r.name} className=\"absolute inset-0 h-full w-full object-cover opacity-45\"/\u003e\u003csvg viewBox=\"0 0 800 500\" className=\"absolute inset-0 h-full w-full\"\u003e\u003cpath d=\"M0 390 C110 280 120 430 250 270 S420 350 520 155 S670 280 800 60\" fill=\"none\" stroke=\"#E8A11A\" strokeWidth=\"3\" strokeDasharray=\"8 12\"/\u003e\u003cpath d=\"M0 440 C180 370 230 460 390 300 S570 370 800 180\" fill=\"none\" stroke=\"#F7F3EA\" strokeWidth=\"1\" opacity=\".7\"/\u003e\u003ccircle cx=\"520\" cy=\"155\" r=\"9\" fill=\"#B3262E\" className=\"animate-pulse\"/\u003e\u003c/svg\u003e\u003cdiv className=\"absolute bottom-0 p-8 text-white\"\u003e\u003cp className=\"font-mono text-[10px] tracking-widest\"\u003eREGION {String(active+1).padStart(2,'0')}\u003c/p\u003e\u003ch3 className=\"display mt-2 text-5xl\"\u003e{r.name}\u003c/h3\u003e\u003cp className=\"mt-2 max-w-md text-sm\"\u003e{r.copy}\u003c/p\u003e\u003c/div\u003e\u003c/div\u003e\u003c/div\u003e\u003c/section\u003e };\n\nexport const FestivalMarquee = () =\u003e \u003cMarquee items={festivals}/\u003e;\n\nexport const FilteredExperiences = () =\u003e { const [filter,setFilter]=useState('all'); const [loading,setLoading]=useState(true); const grid=useRef\u003cHTMLDivElement\u003e(null); const options=['all','beginner','classic','remote','cultural','high altitude']; useEffect(()=\u003e{const t=setTimeout(()=\u003esetLoading(false),240);return()=\u003eclearTimeout(t)},[]); const list=filter==='all'?experiences:experiences.filter(x=\u003ex.tags.includes(filter)||x.difficulty.toLowerCase().includes(filter)); const choose=(x:string)=\u003e{const state=Flip.getState(grid.current?.children || []);setFilter(x);requestAnimationFrame(()=\u003eFlip.from(state,{duration:.55,ease:'power2.inOut',absolute:true}));}; return \u003csection className=\"px-5 py-20 md:px-9\"\u003e\u003cdiv className=\"mx-auto max-w-[1500px]\"\u003e\u003cp className=\"eyebrow\"\u003eField routes\u003c/p\u003e\u003ch2 className=\"display mt-2 text-5xl md:text-7xl\"\u003eChoose your pace.\u003c/h2\u003e\u003cdiv className=\"mt-8 flex flex-wrap gap-2\"\u003e{options.map(x=\u003e\u003cbutton onClick={()=\u003echoose(x)} className={`rounded-full border px-4 py-2 text-xs font-bold capitalize ${filter===x?'border-[var(--brand-500)] bg-[var(--brand-500)] text-white':'border-[var(--border)]'}`} key={x}\u003e{x}\u003c/button\u003e)}\u003c/div\u003e\u003cdiv ref={grid} className=\"mt-10 grid gap-5 sm:grid-cols-2 xl:grid-cols-3\"\u003e{loading?[1,2,3,4,5,6].map(x=\u003e\u003cSkeleton key={x} className=\"h-[480px]\"/\u003e):list.map(x=\u003e\u003cExperienceCard item={x} key={x.slug}/\u003e)}\u003c/div\u003e{!loading\u0026\u0026!list.length\u0026\u0026\u003cp className=\"mt-8 text-center display text-3xl\"\u003eNo route matches this altitude yet.\u003c/p\u003e}\u003c/div\u003e\u003c/section\u003e };\n","src/pages/Pages.tsx":"import React, { useEffect, useState } from 'react';\nimport { z } from 'zod';\nimport { experiences, festivals, regions } from '../data/nepal.ts';\nimport { Hero, ExperienceCard, Stats, AltitudeScene, TrekStrip, RegionTerrain, FestivalMarquee, FilteredExperiences } from '../components/sections/AtlasSections.tsx';\nimport { Accordion, Button, Card, EmptyState, ErrorState } from '../components/ui/primitives.tsx';\n\nconst Section = ({label,title,children,dark=false}:{label:string;title:string;children:React.ReactNode;dark?:boolean}) =\u003e \u003csection className={`${dark?'bg-[var(--brand-900)] text-[var(--brand-50)]':'bg-[var(--bg)]'} px-5 py-20 md:px-9`}\u003e\u003cdiv className=\"mx-auto max-w-[1500px]\"\u003e\u003cp className=\"eyebrow\"\u003e{label}\u003c/p\u003e\u003ch2 className=\"display mt-2 text-5xl md:text-7xl\"\u003e{title}\u003c/h2\u003e\u003cdiv className=\"mt-10\"\u003e{children}\u003c/div\u003e\u003c/div\u003e\u003c/section\u003e;\nexport const Home = () =\u003e \u003c\u003e\u003cHero/\u003e\u003cSection label=\"A country, not a backdrop\" title=\"Many elevations. Many ways of belonging.\"\u003e\u003cdiv className=\"grid gap-8 lg:grid-cols-2\"\u003e\u003cimg width=\"1200\" height=\"800\" loading=\"lazy\" src=\"https://images.unsplash.com/photo-1486911278844-a81c5267e227?w=1200\u0026auto=format\u0026fit=crop\u0026q=80\" alt=\"Prayer flags with Himalayan landscape\" className=\"h-full min-h-[380px] w-full rounded-[var(--r-xl)] object-cover\"/\u003e\u003cp className=\"max-w-xl self-center text-xl leading-relaxed text-[var(--ink-2)]\"\u003eNepal is a place of long conversations: between plains and peaks, Sanskrit and Tibeto-Burman languages, temple bells and river currents. This atlas offers openings rather than shortcuts — practical notes alongside the stories that make a journey meaningful.\u003c/p\u003e\u003c/div\u003e\u003c/Section\u003e\u003cSection label=\"Regional atmospheres\" title=\"Find a different horizon.\"\u003e\u003cdiv className=\"grid gap-5 md:grid-cols-2 xl:grid-cols-4\"\u003e{regions.slice(0,4).map(r=\u003e\u003cCard key={r.name}\u003e\u003cimg width=\"700\" height=\"500\" loading=\"lazy\" src={r.image} alt={r.name} className=\"h-56 w-full object-cover\"/\u003e\u003cdiv className=\"p-5\"\u003e\u003ch3 className=\"display text-3xl\"\u003e{r.name}\u003c/h3\u003e\u003cp className=\"mt-2 text-sm\"\u003e{r.copy}\u003c/p\u003e\u003c/div\u003e\u003c/Card\u003e)}\u003c/div\u003e\u003c/Section\u003e\u003cAltitudeScene/\u003e\u003cFestivalMarquee/\u003e\u003cSection label=\"A few useful numbers\" title=\"A compact country of immense range.\"\u003e\u003cStats/\u003e\u003c/Section\u003e\u003cTrekStrip/\u003e\u003cSection label=\"Plan with context\" title=\"Let the route fit the season.\"\u003e\u003cdiv className=\"rounded-[var(--r-xl)] bg-[var(--brand-500)] p-8 text-white md:flex md:items-end md:justify-between md:p-14\"\u003e\u003cp className=\"display max-w-3xl text-4xl md:text-6xl\"\u003eBuild a considered first draft, then ask local specialists the right questions.\u003c/p\u003e\u003ca href=\"#/plan\"\u003e\u003cButton variant=\"secondary\" className=\"mt-7\"\u003eOpen journey planner\u003c/Button\u003e\u003c/a\u003e\u003c/div\u003e\u003c/Section\u003e\u003c/\u003e;\nexport const Regions = () =\u003e \u003c\u003e\u003cHero title=\"Nepal:\" subtitle=\"drawn in contours.\" image=\"https://images.unsplash.com/photo-1486911278844-a81c5267e227?w=1800\u0026auto=format\u0026fit=crop\u0026q=80\"/\u003e\u003cRegionTerrain/\u003e\u003cSection label=\"Climate note\" title=\"The right season changes with elevation.\"\u003e\u003cdiv className=\"grid gap-4 md:grid-cols-4\"\u003e{[['Terai','60–300m','Warm, humid · Oct–Mar'],['Middle Hills','800–2,000m','Clear mornings · Oct–Nov'],['High valleys','3,000–4,500m','Short summer windows'],['Himalaya','5,000m+','Weather moves quickly']].map(x=\u003e\u003cCard className=\"p-5\" key={x[0]}\u003e\u003cp className=\"eyebrow\"\u003e{x[1]}\u003c/p\u003e\u003ch3 className=\"display mt-4 text-3xl\"\u003e{x[0]}\u003c/h3\u003e\u003cp className=\"mt-3 text-sm\"\u003e{x[2]}\u003c/p\u003e\u003c/Card\u003e)}\u003c/div\u003e\u003c/Section\u003e\u003cSection label=\"Travel thoughtfully\" title=\"Follow local rhythms.\"\u003e\u003cp className=\"max-w-3xl text-lg text-[var(--ink-2)]\"\u003eSeasonality affects roads, trails, festivals and livelihoods. Build flexibility into mountain days, use registered local guides where appropriate, ask before photographing people or rituals, and direct spending toward locally rooted businesses.\u003c/p\u003e\u003c/Section\u003e\u003c/\u003e;\nexport const Treks = () =\u003e \u003c\u003e\u003cHero title=\"Trails:\" subtitle=\"read the terrain.\"/\u003e\u003cFilteredExperiences/\u003e\u003cSection label=\"Before the pass\" title=\"Permits, packing, patience.\"\u003e\u003cdiv className=\"grid gap-5 md:grid-cols-3\"\u003e\u003cCard className=\"p-6\"\u003e\u003ch3 className=\"display text-3xl\"\u003ePermits\u003c/h3\u003e\u003cp className=\"mt-3 text-sm\"\u003eRequirements vary by route and can change. Check official notices and work with registered operators for restricted areas.\u003c/p\u003e\u003c/Card\u003e\u003cCard className=\"p-6\"\u003e\u003ch3 className=\"display text-3xl\"\u003ePack lightly\u003c/h3\u003e\u003cp className=\"mt-3 text-sm\"\u003eLayering, sun protection, water treatment, broken-in footwear and a warm sleep system matter more than excess gear.\u003c/p\u003e\u003c/Card\u003e\u003cCard className=\"p-6\"\u003e\u003ch3 className=\"display text-3xl\"\u003eGo slowly\u003c/h3\u003e\u003cp className=\"mt-3 text-sm\"\u003eAcclimatization is not optional. Build rest days, know symptoms of altitude illness, and descend when advised.\u003c/p\u003e\u003c/Card\u003e\u003c/div\u003e\u003c/Section\u003e\u003c/\u003e;\nexport const Culture = () =\u003e \u003c\u003e\u003cHero title=\"Living\" subtitle=\"heritage.\" image=\"https://images.unsplash.com/photo-1518105779142-d975f22f1b0a?w=1800\u0026auto=format\u0026fit=crop\u0026q=80\"/\u003e\u003cSection label=\"Festival calendar\" title=\"Days held in community.\"\u003e\u003cdiv className=\"grid gap-px bg-[var(--border)] md:grid-cols-3\"\u003e{festivals.map((f,i)=\u003e\u003cdiv className=\"bg-[var(--surface)] p-7\" key={f}\u003e\u003cp className=\"font-mono text-xs text-[var(--brand-500)]\"\u003e{String(i+1).padStart(2,'0')}\u003c/p\u003e\u003ch3 className=\"display mt-8 text-3xl\"\u003e{f}\u003c/h3\u003e\u003cp className=\"mt-3 text-sm\"\u003eObserve with invitation, context and care for the people keeping these traditions alive.\u003c/p\u003e\u003c/div\u003e)}\u003c/div\u003e\u003c/Section\u003e\u003cSection label=\"A small etiquette guide\" title=\"Enter gently.\"\u003e\u003cdiv className=\"grid gap-6 md:grid-cols-2\"\u003e\u003cp\u003eRemove shoes where requested. Dress with care at religious sites. Ask before taking portraits. Circumambulate stupas and chortens clockwise when joining the flow. Learn a few Nepali greetings and accept that some spaces are not for visitors.\u003c/p\u003e\u003cp\u003eHeritage is not frozen in time: temples, courtyards and rituals are workplaces, homes and places of devotion. Give more time than you think you need.\u003c/p\u003e\u003c/div\u003e\u003c/Section\u003e\u003c/\u003e;\nexport const FoodCrafts = () =\u003e \u003c\u003e\u003cHero title=\"Steam, spice,\" subtitle=\"and skilled hands.\" image=\"https://images.unsplash.com/photo-1601050690597-df0568f70950?w=1800\u0026auto=format\u0026fit=crop\u0026q=80\"/\u003e\u003cSection label=\"At the table\" title=\"Taste by region.\"\u003e\u003cdiv className=\"grid gap-5 md:grid-cols-2 xl:grid-cols-4\"\u003e{[['Momo','Folded dumplings, shared hot from the steamer.','photo-1601050690597-df0568f70950'],['Dal bhat','Rice, lentils and seasonal accompaniments.','photo-1585937421612-70a008356fbe'],['Mountain tea','Salt, butter, milk or fragrant leaf — hospitality has many cups.','photo-1544787219-7f47ccb76574'],['Dhaka textile','A vivid woven language of pattern and place.','photo-1528459801416-a9e53bbf4e17']].map(([n,c,id])=\u003e\u003cCard key={n}\u003e\u003cimg width=\"700\" height=\"500\" loading=\"lazy\" src={`https://images.unsplash.com/${id}?w=800\u0026auto=format\u0026fit=crop\u0026q=80`} alt={n} className=\"h-56 w-full object-cover\"/\u003e\u003cdiv className=\"p-5\"\u003e\u003ch3 className=\"display text-3xl\"\u003e{n}\u003c/h3\u003e\u003cp className=\"mt-2 text-sm\"\u003e{c}\u003c/p\u003e\u003c/div\u003e\u003c/Card\u003e)}\u003c/div\u003e\u003c/Section\u003e\u003cSection label=\"Craft, not souvenir\" title=\"Look for makers, materials, provenance.\"\u003e\u003cp className=\"max-w-3xl text-lg\"\u003eThangka painters, lokta paper makers, metalworkers, wood carvers and weavers sustain deep bodies of knowledge. Buy directly when possible, ask about process, and avoid antiques or sacred objects without clear provenance.\u003c/p\u003e\u003c/Section\u003e\u003c/\u003e;\nexport const Guide = () =\u003e \u003c\u003e\u003cHero title=\"Useful\" subtitle=\"field notes.\" image=\"https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?w=1800\u0026auto=format\u0026fit=crop\u0026q=80\"/\u003e\u003cSection label=\"Practical, not official advice\" title=\"Start with the basics.\"\u003e\u003cdiv className=\"grid gap-5 md:grid-cols-2 xl:grid-cols-3\"\u003e{[['When to visit','Oct–Nov and Mar–Apr often bring clearer mountain views; monsoon transforms travel patterns.'],['Entry \u0026 visa','Rules change. Use Nepal’s official immigration sources and your nearest embassy before travel.'],['Money','Nepalese rupees are used locally. Carry a mix of cash and cards; mountain access varies.'],['Transport','Road journeys can be slow. Domestic flights are weather-dependent. Keep buffer days.'],['Connectivity','SIM access is straightforward in cities; coverage fades on many trails. Download maps offline.'],['Health \u0026 altitude','Insurance, water hygiene and conservative acclimatization deserve attention before every trek.']].map(x=\u003e\u003cCard className=\"p-6\" key={x[0]}\u003e\u003cp className=\"eyebrow\"\u003eTravel note\u003c/p\u003e\u003ch3 className=\"display mt-3 text-3xl\"\u003e{x[0]}\u003c/h3\u003e\u003cp className=\"mt-3 text-sm\"\u003e{x[1]}\u003c/p\u003e\u003c/Card\u003e)}\u003c/div\u003e\u003c/Section\u003e\u003c/\u003e;\nexport const Stories = () =\u003e { const [search,setSearch]=useState(''); const list=experiences.filter(x=\u003ex.name.toLowerCase().includes(search.toLowerCase())||x.location.toLowerCase().includes(search.toLowerCase())); return \u003c\u003e\u003cHero title=\"Stories\" subtitle=\"from the long road.\"/\u003e\u003cSection label=\"The journal\" title=\"Read the country slowly.\"\u003e\u003cinput aria-label=\"Search stories\" value={search} onChange={e=\u003esetSearch(e.target.value)} placeholder=\"Search field notes\" className=\"mb-8 w-full max-w-md rounded-full border-[var(--border)] bg-[var(--surface)] px-5 py-3\"/\u003e\u003cdiv className=\"grid gap-5 md:grid-cols-3\"\u003e{list.slice(0,6).map(x=\u003e\u003cExperienceCard item={x} key={x.slug}/\u003e)}\u003c/div\u003e{!list.length\u0026\u0026\u003cEmptyState label=\"No field note matches this search yet\"/\u003e}\u003c/Section\u003e\u003c/\u003e };\nconst planSchema=z.object({name:z.string().min(2,'Please add your name'),email:z.string().email('Use a valid email'),region:z.string().min(1,'Choose a region'),days:z.coerce.number().min(1).max(60),group:z.coerce.number().min(1).max(20),notes:z.string().max(500)});\nexport const Plan = () =\u003e { const [result,setResult]=useState(''); const [errors,setErrors]=useState\u003cRecord\u003cstring,string\u003e\u003e({}); const [failed,setFailed]=useState(false); const submit=(e:React.FormEvent\u003cHTMLFormElement\u003e)=\u003e{e.preventDefault();const raw=Object.fromEntries(new FormData(e.currentTarget));const p=planSchema.safeParse(raw);if(!p.success){const next:Record\u003cstring,string\u003e={};p.error.issues.forEach(i=\u003enext[String(i.path[0])]=i.message);setErrors(next);return;}localStorage.setItem('nepal-plan',JSON.stringify(p.data));setErrors({});setResult(`${p.data.name}, your ${p.data.days}-day ${p.data.region} sketch is saved locally. Begin with two flexible days and confirm route conditions with local experts.`);}; return \u003c\u003e\u003cHero title=\"Plan a\" subtitle=\"thoughtful journey.\" image=\"https://images.unsplash.com/photo-1589884629108-3193400c7cc9?w=1800\u0026auto=format\u0026fit=crop\u0026q=80\"/\u003e\u003cSection label=\"Your first draft\" title=\"A few good questions.\"\u003e\u003cdiv className=\"grid gap-10 lg:grid-cols-[1.2fr_.8fr]\"\u003e\u003cform onSubmit={submit} className=\"rounded-[var(--r-xl)] bg-[var(--surface)] p-6 md:p-9\"\u003e\u003cdiv className=\"grid gap-5 md:grid-cols-2\"\u003e{[['name','Traveler name','text'],['email','Email','email'],['days','Trip length (days)','number'],['group','Group size','number']].map(([n,l,t])=\u003e\u003clabel className=\"text-sm font-bold\" key={n}\u003e{l}\u003cinput name={n} type={t} min=\"1\" className=\"mt-2 w-full rounded-[var(--r-sm)] border-[var(--border)] bg-[var(--bg)]\"/\u003e{errors[n]\u0026\u0026\u003csmall className=\"text-[var(--danger)]\"\u003e{errors[n]}\u003c/small\u003e}\u003c/label\u003e)}\u003clabel className=\"text-sm font-bold\"\u003ePreferred region\u003cselect name=\"region\" className=\"mt-2 w-full rounded-[var(--r-sm)] border-[var(--border)] bg-[var(--bg)]\"\u003e\u003coption value=\"\"\u003eChoose a region\u003c/option\u003e{regions.map(r=\u003e\u003coption key={r.name}\u003e{r.name}\u003c/option\u003e)}\u003c/select\u003e{errors.region\u0026\u0026\u003csmall className=\"text-[var(--danger)]\"\u003e{errors.region}\u003c/small\u003e}\u003c/label\u003e\u003clabel className=\"text-sm font-bold\"\u003eDifficulty\u003cselect name=\"difficulty\" className=\"mt-2 w-full rounded-[var(--r-sm)] border-[var(--border)] bg-[var(--bg)]\"\u003e\u003coption\u003eEasy\u003c/option\u003e\u003coption\u003eModerate\u003c/option\u003e\u003coption\u003eChallenging\u003c/option\u003e\u003c/select\u003e\u003c/label\u003e\u003c/div\u003e\u003clabel className=\"mt-5 block text-sm font-bold\"\u003eNotes\u003ctextarea name=\"notes\" maxLength={500} className=\"mt-2 w-full rounded-[var(--r-sm)] border-[var(--border)] bg-[var(--bg)]\" rows={4} placeholder=\"Interests, access needs, pace, questions…\"/\u003e\u003c/label\u003e\u003cButton className=\"mt-6\"\u003eGenerate a gentle first draft\u003c/Button\u003e\u003c/form\u003e\u003caside\u003e{failed?\u003cErrorState retry={()=\u003esetFailed(false)}/\u003e:\u003cCard className=\"p-7\"\u003e\u003cp className=\"eyebrow\"\u003ePlanner note\u003c/p\u003e\u003ch3 className=\"display mt-4 text-4xl\"\u003eRoutes need room to change.\u003c/h3\u003e\u003cp className=\"mt-4 text-sm\"\u003eThis is an offline planning aid, not a booking service. Weather, permits, roads and community calendars deserve a final local check.\u003c/p\u003e\u003cbutton className=\"mt-5 text-sm text-[var(--brand-500)] underline\" onClick={()=\u003esetFailed(true)}\u003eSimulate a connection issue\u003c/button\u003e\u003c/Card\u003e}{result\u0026\u0026\u003cCard className=\"mt-5 border-[var(--brand-500)] p-7\"\u003e\u003cp className=\"eyebrow\"\u003eSaved locally\u003c/p\u003e\u003cp className=\"display mt-3 text-3xl\"\u003e{result}\u003c/p\u003e\u003c/Card\u003e}\u003c/aside\u003e\u003c/div\u003e\u003c/Section\u003e\u003c/\u003e;\nexport const Detail = ({slug}:{slug:string}) =\u003e { const item=experiences.find(x=\u003ex.slug===slug); return item?\u003c\u003e\u003cHero title={item.name.split(' ').slice(0,2).join(' ')} subtitle={item.location} image={item.image}/\u003e\u003cSection label={`${item.location} · ${item.season}`} title={item.name}\u003e\u003cdiv className=\"grid gap-8 lg:grid-cols-[1.3fr_.7fr]\"\u003e\u003cp className=\"text-xl leading-relaxed\"\u003e{item.description}\u003c/p\u003e\u003cCard className=\"p-6\"\u003e\u003cp className=\"eyebrow\"\u003eRoute facts\u003c/p\u003e\u003cp className=\"mt-4 font-mono text-sm\"\u003eESTIMATE · {item.price}\u003c/p\u003e\u003cp className=\"mt-2 font-mono text-sm\"\u003ePACE · {itemdays} days\u003c/p\u003e\u003cp className=\"mt-2 font-mono text-sm\"\u003eALTITUDE · {item.altitude}\u003c/p\u003e\u003cp className=\"mt-2 font-mono text-sm\"\u003eDIFFICULTY · {item.difficulty}\u003c/p\u003e\u003c/Card\u003e\u003c/div\u003e\u003c/Section\u003e\u003cTrekStrip/\u003e\u003c/\u003e:\u003cEmptyState label=\"That route has moved beyond this edition of the atlas.\"/\u003e;\nexport const About = () =\u003e \u003c\u003e\u003cHero title=\"An atlas for\" subtitle=\"looking closer.\" image=\"https://images.unsplash.com/photo-1548013146-72479768bada?w=1800\u0026auto=format\u0026fit=crop\u0026q=80\"/\u003e\u003cSection label=\"Our position\" title=\"Nepal is living, not scenery.\"\u003e\u003cdiv className=\"grid gap-8 lg:grid-cols-[1.2fr_.8fr]\"\u003e\u003cp className=\"max-w-3xl text-xl leading-relaxed text-[var(--ink-2)]\"\u003eNepal Atlas is an independent editorial guide made for visitors who want practical clarity without flattening a complex country into an itinerary. We arrange routes, seasons, food, heritage and travel notes as starting points for more attentive travel.\u003c/p\u003e\u003cCard className=\"p-7\"\u003e\u003cp className=\"eyebrow\"\u003eEditorial promise\u003c/p\u003e\u003cp className=\"display mt-4 text-3xl\"\u003eCredit people. Check conditions. Leave room for local knowledge.\u003c/p\u003e\u003c/Card\u003e\u003c/div\u003e\u003c/Section\u003e\u003cSection label=\"Respect note\" title=\"Images have contexts.\"\u003e\u003cp className=\"max-w-3xl text-lg\"\u003ePhotographs in this demonstration atlas are illustrative editorial references. In practice, image-making at religious sites, homes, workshops and festivals should begin with consent. Avoid reducing communities to costumes, and consider supporting guides, makers and conservation groups rooted in each place.\u003c/p\u003e\u003c/Section\u003e\u003c/\u003e;\nexport const Heritage = () =\u003e \u003c\u003e\u003cHero title=\"Brick, bell,\" subtitle=\"and memory.\" image=\"https://images.unsplash.com/photo-1544735716-392fe2489ffa?w=1800\u0026auto=format\u0026fit=crop\u0026q=80\"/\u003e\u003cSection label=\"Built heritage\" title=\"Courtyards that remain in use.\"\u003e\u003cdiv className=\"grid gap-5 md:grid-cols-2 xl:grid-cols-3\"\u003e{experiences.filter(x=\u003e['Kathmandu Valley','Lumbini','Patan'].some(y=\u003ex.location.includes(y))).map(x=\u003e\u003cExperienceCard item={x} key={x.slug}/\u003e)}\u003c/div\u003e\u003c/Section\u003e\u003cSection label=\"Conservation\" title=\"Visit with a lighter footprint.\"\u003e\u003cp className=\"max-w-3xl text-lg\"\u003eHeritage zones are active neighborhoods as well as historic places. Respect barriers and restoration work, hire locally where possible, and keep pathways clear during ceremonies. Admission fees and community-led enterprises can form part of long-term care when transparently managed.\u003c/p\u003e\u003c/Section\u003e\u003c/\u003e;\nexport const Gallery = () =\u003e { const [kind,setKind]=useState('All'); const [selected,setSelected]=useState\u003cnumber|null\u003e(null); const gallery=[...experiences,...regions].map((x,i)=\u003e({name:x.name,image:x.image,location:'location' in x?x.location:'Nepal',kind:['Mountains','Cities','Heritage','Food','Festivals','Wildlife'][i%6]})); const shown=kind==='All'?gallery:gallery.filter(x=\u003ex.kind===kind); useEffect(()=\u003e{const onKey=(e:KeyboardEvent)=\u003e{if(e.key==='Escape')setSelected(null);};window.addEventListener('keydown',onKey);return()=\u003ewindow.removeEventListener('keydown',onKey);},[]); return \u003c\u003e\u003cHero title=\"A visual\" subtitle=\"field archive.\" image=\"https://images.unsplash.com/photo-1518002054494-3a6f94352e9d?w=1800\u0026auto=format\u0026fit=crop\u0026q=80\"/\u003e\u003cSection label=\"Image index\" title=\"Places, held briefly.\"\u003e\u003cdiv className=\"mb-8 flex flex-wrap gap-2\"\u003e{['All','Mountains','Cities','Heritage','Food','Festivals','Wildlife'].map(x=\u003e\u003cbutton onClick={()=\u003esetKind(x)} className={`rounded-full border px-4 py-2 text-xs font-bold ${kind===x?'border-[var(--brand-500)] bg-[var(--brand-500)] text-white':'border-[var(--border)]'}`} key={x}\u003e{x}\u003c/button\u003e)}\u003c/div\u003e{shown.length?\u003cdiv className=\"columns-1 gap-5 md:columns-2 xl:columns-3\"\u003e{shown.map((x,i)=\u003e\u003cbutton key={`${x.name}-${i}`} onClick={()=\u003esetSelected(i)} className=\"mb-5 block w-full overflow-hidden rounded-[var(--r)] text-left\"\u003e\u003cimg width=\"1000\" height=\"760\" loading=\"lazy\" src={x.image} alt={`${x.name}, ${x.location}`} className=\"w-full transition duration-500 hover:scale-105\"/\u003e\u003cspan className=\"block bg-[var(--surface)] p-3 text-xs\"\u003e\u003cb\u003e{x.name}\u003c/b\u003e · {x.location}\u003c/span\u003e\u003c/button\u003e)}\u003c/div\u003e:\u003cEmptyState label=\"No images match that field label.\"/\u003e}\u003c/Section\u003e{selected!==null\u0026\u0026shown[selected]\u0026\u0026\u003cdiv className=\"fixed inset-0 z-[90] grid place-items-center bg-[var(--brand-900)]/95 p-5\" role=\"dialog\" aria-modal=\"true\" aria-label=\"Image lightbox\"\u003e\u003cbutton onClick={()=\u003esetSelected(null)} className=\"absolute right-6 top-6 rounded-full border border-white/50 px-5 py-2 text-sm text-white\"\u003eClose\u003c/button\u003e\u003cfigure className=\"max-h-full max-w-5xl\"\u003e\u003cimg width=\"1600\" height=\"1100\" src={shown[selected].image} alt={shown[selected].name} className=\"max-h-[78vh] w-full object-contain\"/\u003e\u003cfigcaption className=\"mt-4 text-center text-sm text-white\"\u003e{shown[selected].name} · {shown[selected].location}\u003c/figcaption\u003e\u003c/figure\u003e\u003c/div\u003e}\u003csection className=\"relative h-[55vh] overflow-hidden\"\u003e\u003cvideo muted playsInline autoPlay loop preload=\"metadata\" poster=\"https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?w=1600\u0026auto=format\u0026fit=crop\u0026q=80\" className=\"h-full w-full object-cover\"\u003e\u003csource src=\"https://assets.mixkit.co/videos/preview/mixkit-clouds-over-mountains-1187-large.mp4\" type=\"video/mp4\"/\u003e\u003c/video\u003e\u003cdiv className=\"absolute inset-0 grid place-items-center bg-[var(--brand-900)]/45 text-center text-white\"\u003e\u003cdiv\u003e\u003cp className=\"eyebrow text-[var(--brand-100)]\"\u003eAmbient archive\u003c/p\u003e\u003ch2 className=\"display mt-3 text-5xl md:text-7xl\"\u003eClouds write slowly.\u003c/h2\u003e\u003c/div\u003e\u003c/div\u003e\u003c/section\u003e\u003c/\u003e;\nexport const NotFound = () =\u003e \u003csection className=\"grid min-h-[70vh] place-items-center px-5 text-center\"\u003e\u003cdiv\u003e\u003cp className=\"eyebrow\"\u003e404 / Lost on the map\u003c/p\u003e\u003ch1 className=\"display mt-3 text-6xl\"\u003eThis path is not charted.\u003c/h1\u003e\u003ca href=\"#/\"\u003e\u003cButton className=\"mt-7\"\u003eReturn to the atlas\u003c/Button\u003e\u003c/a\u003e\u003c/div\u003e\u003c/section\u003e;\n","src/App.tsx":"import React, { useEffect, useState } from 'react';\nimport { Layout } from './components/layout/Layout.tsx';\nimport { ScrollTrigger } from './lib/gsap.ts';\nimport { About, Culture, Detail, FoodCrafts, Gallery, Guide, ഹെറitage, Home, NotFound, Plan, Regions, Stories, Treks } from './pages/Pages.tsx';\n\nconst readRoute = () =\u003e window.location.hash.replace(/^#/, '') || '/';\n\nexport const App = () =\u003e {\n const [route, setRoute] = useState(readRoute());\n\n useEffect(() =\u003e {\n const update = () =\u003e {\n setRoute(readRoute());\n window.scrollTo({ top: 0, behavior: 'instant' as ScrollBehavior });\n setTimeout(() =\u003e ScrollTrigger.refresh(), 80);\n };\n window.addEventListener('hashchange', update);\n return () =\u003e window.removeEventListener('hashchange', update);\n }, []);\n\n const path = route.split('?')[0];\n const query = new URLSearchParams(route.split('?')[1] || '');\n let page: React.ReactNode = \u003cNotFound /\u003e;\n\n if (path === '/') page = \u003cHome /\u003e;\n if (path === '/regions') page = \u003cRegions /\u003e;\n if (path === '/treks') page = \u003cTreks /\u003e;\n if (path === '/heritage') page = \u003cHeritage /\u003e;\n if (path === '/culture') page = \u003cCulture /\u003e;\n if (path === '/food') page = \u003cFoodCrafts /\u003e;\n if (path === '/planning' || path === '/plan') page = \u003cGuide /\u003e;\n if (path === '/gallery') page = \u003cGallery /\u003e;\n if (path === '/about') page = \u003cAbout /\u003e;\n if (path === '/contact') page = \u003cPlan /\u003e;\n if (path === '/stories') page = \u003cStories /\u003e;\n if (path === '/route') page = \u003cDetail slug={query.get('id') || ''} /\u003e;\n\n return \u003cLayout\u003e{page}\u003c/Layout\u003e;\n};\n","src/main.tsx":"import React from 'react';\nimport { createRoot } from 'react-dom/client';\nimport { App } from './App.tsx';\nimport './lib/lenis.ts';\n\nconst root = document.getElementById('root');\n\nif (root) {\n createRoot(root).render(\u003cApp /\u003e);\n}\n","README.md":"# Nepal Atlas\n\nA browser-native React 19 editorial guide to Nepal, designed as a quiet Himalayan museum archive rather than a conventional tourism landing page.\n\n## Art direction\n\n**Editorial Himalayan Museum Minimalism** combines Fraunces display typography, Manrope utility type, lokta-paper neutrals, Kathmandu brick, temple gold, Himalayan teal, thin cartographic rules and documentary photography. The UI treats places as annotated field notes.\n\n## Architecture\n\n- `src/data/nepal.ts` contains locally seeded, zod-validated route, region and festival content.\n- `src/components/sections/AtlasSections.tsx` contains the cinematic hero, GSAP stat counters, horizontal route strip, pinned altitude narrative, region terrain selector and filterable route grid.\n- `src/pages/Pages.tsx` contains hash-routed editorial pages.\n- `src/components/ui/primitives.tsx` supplies accessible shadcn-inspired primitives and state components.\n- `src/lib/gsap.ts` registers GSAP plugins; `src/lib/lenis.ts` integrates smooth scrolling with ScrollTrigger.\n\n## Page map\n\n`#/` Home · `#/regions` · `#/treks` · `#/heritage` · `#/culture` · `#/food` · `#/planning` · `#/gallery` · `#/about` · `#/contact` · `#/stories`.\n\n## Notes\n\nThis guide is an offline editorial prototype. Verify permits, immigration rules, route conditions, weather, emergency information and cultural access with official and locally rooted sources before travel.\n"};window.__MM_ENTRY__="src/main.tsx";window.__MM_EXTERNAL_IMPORTS__={"react":"https://esm.sh/react@19.2.0","react/":"https://esm.sh/react@19.2.0/","react/jsx-runtime":"https://esm.sh/react@19.2.0/jsx-runtime","react-dom":"https://esm.sh/react-dom@19.2.0?deps=react@19.2.0","react-dom/":"https://esm.sh/react-dom@19.2.0/","react-dom/client":"https://esm.sh/react-dom@19.2.0/client?deps=react@19.2.0","gsap":"https://esm.sh/gsap@3.12.5","gsap/":"https://esm.sh/gsap@3.12.5/","gsap/ScrollTrigger":"https://esm.sh/gsap@3.12.5/ScrollTrigger","gsap/Flip":"https://esm.sh/gsap@3.12.5/Flip","gsap/Observer":"https://esm.sh/gsap@3.12.5/Observer","lenis":"https://esm.sh/lenis@1.1.20","lenis/":"https://esm.sh/lenis@1.1.20/","@studio-freight/lenis":"https://esm.sh/@studio-freight/lenis@1.0.42","@studio-freight/lenis/":"https://esm.sh/@studio-freight/lenis@1.0.42/","clsx":"https://esm.sh/clsx@2.1.1","tailwind-merge":"https://esm.sh/tailwind-merge@3.3.1","class-variance-authority":"https://esm.sh/class-variance-authority@0.7.1","lucide-react":"https://esm.sh/lucide-react@0.469.0?deps=react@19.2.0","lucide-react/":"https://esm.sh/lucide-react@0.469.0/","zod":"https://esm.sh/zod@3.24.2","zod/":"https://esm.sh/zod@3.24.2/","three":"https://esm.sh/three@0.171.0","three/":"https://esm.sh/three@0.171.0/","framer-motion":"https://esm.sh/framer-motion@12.23.24?deps=react@19.2.0,react-dom@19.2.0"}; Nepal — The Living Himalaya
MMade with MythMind AI