Repository navigation
Expand file tree
/
Copy pathindex.html
More file actions
1 lines (1 loc) · 42.4 KB
/
Copy pathindex.html
File metadata and controls
1 lines (1 loc) · 42.4 KB
1
<!DOCTYPE html><html lang="en-NZ" class="bg-background archivo_9443aef7-module__vKFuNW__variable ibm_plex_mono_28411002-module__cjC0Ca__variable"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/_next/static/media/75affa71d1e2f6a7-s.p.17-aodiw50953.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/99e609270109b47d-s.p.40sczeszzbjw1.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/effe91970fc4db64-s.p.0oace-s_gkfks.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/icon.png?v=8499e28e8b" as="image"/><link rel="preload" href="/icons/bodycap.png?v=07305f9832" as="image"/><link rel="preload" href="/projects/bodycap.png?v=59fda9c60c" as="image"/><link rel="preload" href="/icons/hotshoe.png?v=82505950b6" as="image"/><link rel="stylesheet" href="/_next/static/chunks/3-f-w91wsp8zu.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/068tv5jdpv59c.js"/><script src="/_next/static/chunks/0fp66e41x4xz5.js" async=""></script><script src="/_next/static/chunks/1pxn44xleb8o7.js" async=""></script><script src="/_next/static/chunks/turbopack-30o8ffguptx6-.js" async=""></script><script src="/_next/static/chunks/017i2_0_yuh4o.js" async=""></script><script src="/_next/static/chunks/14hf65ykvrs0z.js" async=""></script><meta name="theme-color" content="#0f0e0d"/><meta name="color-scheme" content="dark"/><title>XE1AF35: Small, local-first tools for photographers</title><meta name="description" content="Independent projects exploring where photography and software meet. Each one runs in your browser, works offline, and keeps your data on your own device."/><link rel="icon" href="/icon.png?icon.20_jeyolqkyei.png" sizes="100x100" type="image/png"/><link rel="apple-touch-icon" href="/apple-icon.png?apple-icon.3x8few6mnfmg3.png" sizes="180x180" type="image/png"/><meta name="next-size-adjust" content=""/><script src="/_next/static/chunks/0cz1d0mv5g_q7.js" noModule=""></script></head><body class="font-sans antialiased"><div hidden=""><!--$--><!--/$--></div><div id="top" class="mx-auto min-h-dvh w-full max-w-6xl px-4 sm:px-8 lg:px-12"><header class="flex items-center justify-between gap-4 border-b border-border py-5"><a href="#top" class="inline-flex items-center gap-2 font-mono text-sm font-medium tracking-[0.15em] text-foreground"><img src="/icon.png?v=8499e28e8b" alt="" width="24" height="24" class="size-6"/>XE1AF35</a><nav aria-label="Main" class="flex items-center gap-5 text-sm text-muted-foreground"><a href="#projects" class="transition-colors hover:text-foreground">Projects</a><a href="#principles" class="hidden transition-colors hover:text-foreground sm:inline">Principles</a><a href="https://github.com/XE1AF35" target="_blank" rel="noreferrer" class="inline-flex items-center gap-2 transition-colors hover:text-foreground"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" class="size-4"><path d="M12 .3a12 12 0 0 0-3.8 23.4c.6.1.8-.3.8-.6v-2c-3.3.7-4-1.6-4-1.6-.6-1.4-1.4-1.8-1.4-1.8-1-.7.1-.7.1-.7 1.2.1 1.8 1.2 1.8 1.2 1 1.8 2.8 1.3 3.5 1 .1-.8.4-1.3.7-1.6-2.7-.3-5.5-1.3-5.5-6 0-1.2.5-2.3 1.3-3.1-.2-.4-.6-1.6 0-3.2 0 0 1-.3 3.4 1.2a11.5 11.5 0 0 1 6 0C17.3 4.7 18.3 5 18.3 5c.6 1.6.2 2.8.1 3.2.8.8 1.3 1.9 1.3 3.1 0 4.6-2.8 5.6-5.5 5.9.5.4.9 1.1.9 2.2v3.3c0 .3.2.7.8.6A12 12 0 0 0 12 .3"></path></svg><span class="sr-only sm:not-sr-only">GitHub</span></a></nav></header><main><section aria-labelledby="tagline" class="py-20 sm:py-28 lg:py-36"><p class="font-mono text-[0.7rem] uppercase tracking-[0.2em] text-primary">2<!-- --> projects · Photography × software</p><h1 id="tagline" class="mt-6 max-w-4xl text-balance text-5xl font-semibold leading-[0.95] tracking-tight sm:text-7xl lg:text-8xl">Small, local-first tools for photographers.</h1><p class="mt-8 max-w-2xl text-pretty text-lg leading-relaxed text-muted-foreground">Independent projects exploring where photography and software meet. Each one runs in your browser, works offline, and keeps your data on your own device.</p><a href="#projects" class="group mt-10 inline-flex items-center gap-2 text-sm font-medium text-foreground transition-colors hover:text-primary">See the projects<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-arrow-down size-4 text-muted-foreground transition-transform duration-300 group-hover:translate-y-0.5 group-hover:text-primary" aria-hidden="true"><path d="M12 5v14"></path><path d="m19 12-7 7-7-7"></path></svg></a></section><section id="projects" aria-labelledby="projects-heading" class="scroll-mt-6"><h2 id="projects-heading" class="font-mono text-[0.7rem] uppercase tracking-[0.2em] pb-6 text-primary">Projects</h2><article aria-labelledby="bodycap" class="border-t border-border py-16 sm:py-20"><div class="grid grid-cols-1 gap-10 lg:grid-cols-12 lg:gap-14"><div class="min-w-0 lg:col-span-5"><p class="font-mono text-[0.7rem] uppercase tracking-[0.2em] text-muted-foreground"><span class="text-primary">01</span><span> · <!-- -->Web app</span><span> · <!-- -->Any device</span><span> · <!-- -->Works offline</span></p><h3 id="bodycap" class="mt-5 flex items-center gap-4 text-4xl font-semibold tracking-tight sm:text-5xl"><img src="/icons/bodycap.png?v=07305f9832" alt="" width="48" height="48" class="size-10 shrink-0 sm:size-12"/>Bodycap</h3><p class="mt-3 text-xl text-foreground/90">Your camera gear, organised.</p><p class="mt-5 text-pretty leading-relaxed text-muted-foreground">Keep track of every body, lens, flash, and bag you own, with serial numbers, what you paid, warranties, and where it all is. It never needs an account.</p><ul class="mt-6 space-y-3"><li class="flex gap-3 text-sm leading-relaxed text-foreground/85"><span class="mt-2 size-1.5 shrink-0 bg-primary" aria-hidden="true"></span>Suggests models as you type, from a built-in catalogue of camera bodies and lenses, and fills in their specs</li><li class="flex gap-3 text-sm leading-relaxed text-foreground/85"><span class="mt-2 size-1.5 shrink-0 bg-primary" aria-hidden="true"></span>Kits that double as packing checklists, and can be shared as a link</li><li class="flex gap-3 text-sm leading-relaxed text-foreground/85"><span class="mt-2 size-1.5 shrink-0 bg-primary" aria-hidden="true"></span>A log of shoots, showing how often each item is used and what has sat unused</li><li class="flex gap-3 text-sm leading-relaxed text-foreground/85"><span class="mt-2 size-1.5 shrink-0 bg-primary" aria-hidden="true"></span>What you spend each year, and what your gear is worth now</li><li class="flex gap-3 text-sm leading-relaxed text-foreground/85"><span class="mt-2 size-1.5 shrink-0 bg-primary" aria-hidden="true"></span>Loans, a maintenance log, and an insurance list ready to print</li><li class="flex gap-3 text-sm leading-relaxed text-foreground/85"><span class="mt-2 size-1.5 shrink-0 bg-primary" aria-hidden="true"></span>Which lenses fit which cameras, with a map of your whole system</li></ul><div class="mt-8 flex flex-wrap gap-3"><a href="https://xe1af35.github.io/bodycap/" target="_blank" rel="noreferrer" class="group inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary bg-primary text-primary-foreground hover:bg-primary/85">Open <!-- -->Bodycap<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-arrow-up-right size-4 transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:translate-x-0.5" aria-hidden="true"><path d="M7 7h10v10"></path><path d="M7 17 17 7"></path></svg></a><a href="https://github.com/XE1AF35/bodycap" target="_blank" rel="noreferrer" class="group inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary border border-border text-foreground hover:border-primary hover:text-primary"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" class="size-4"><path d="M12 .3a12 12 0 0 0-3.8 23.4c.6.1.8-.3.8-.6v-2c-3.3.7-4-1.6-4-1.6-.6-1.4-1.4-1.8-1.4-1.8-1-.7.1-.7.1-.7 1.2.1 1.8 1.2 1.8 1.2 1 1.8 2.8 1.3 3.5 1 .1-.8.4-1.3.7-1.6-2.7-.3-5.5-1.3-5.5-6 0-1.2.5-2.3 1.3-3.1-.2-.4-.6-1.6 0-3.2 0 0 1-.3 3.4 1.2a11.5 11.5 0 0 1 6 0C17.3 4.7 18.3 5 18.3 5c.6 1.6.2 2.8.1 3.2.8.8 1.3 1.9 1.3 3.1 0 4.6-2.8 5.6-5.5 5.9.5.4.9 1.1.9 2.2v3.3c0 .3.2.7.8.6A12 12 0 0 0 12 .3"></path></svg>Source<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-arrow-up-right size-4 transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:translate-x-0.5" aria-hidden="true"><path d="M7 7h10v10"></path><path d="M7 17 17 7"></path></svg></a></div></div><div class="min-w-0 lg:col-span-7"><a href="https://xe1af35.github.io/bodycap/" target="_blank" rel="noreferrer" class="viewfinder group block focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-primary"><img src="/projects/bodycap.png?v=59fda9c60c" alt="The Bodycap dashboard, with a warranty running out, gear counts, a camera on loan, what the gear is worth by category, and backup status" width="1320" height="960" loading="eager" class="block h-auto w-full transition-opacity duration-300 group-hover:opacity-90"/><span class="sr-only">Open <!-- -->Bodycap</span></a></div></div></article><article aria-labelledby="hotshoe" class="border-t border-border py-16 sm:py-20"><div class="grid grid-cols-1 gap-10 lg:grid-cols-12 lg:gap-14"><div class="min-w-0 lg:col-span-5"><p class="font-mono text-[0.7rem] uppercase tracking-[0.2em] text-muted-foreground"><span class="text-primary">02</span><span> · <!-- -->iPhone</span><span> · <!-- -->Home Screen app</span><span> · <!-- -->Works offline</span></p><h3 id="hotshoe" class="mt-5 flex items-center gap-4 text-4xl font-semibold tracking-tight sm:text-5xl"><img src="/icons/hotshoe.png?v=82505950b6" alt="" width="48" height="48" class="size-10 shrink-0 sm:size-12"/>Hotshoe</h3><p class="mt-3 text-xl text-foreground/90">Where you took the photo, in one tap.</p><p class="mt-5 text-pretty leading-relaxed text-muted-foreground">Log your location as you shoot, then geotag your photos later. It's made for cameras that don't record where a photo was taken.</p><ul class="mt-6 space-y-3"><li class="flex gap-3 text-sm leading-relaxed text-foreground/85"><span class="mt-2 size-1.5 shrink-0 bg-primary" aria-hidden="true"></span>Waits for an accurate fix, and marks the ones that fall short</li><li class="flex gap-3 text-sm leading-relaxed text-foreground/85"><span class="mt-2 size-1.5 shrink-0 bg-primary" aria-hidden="true"></span>Adds entries from photos already in your library, using their own time and location</li><li class="flex gap-3 text-sm leading-relaxed text-foreground/85"><span class="mt-2 size-1.5 shrink-0 bg-primary" aria-hidden="true"></span>A map of each day's entries, with a trail showing the route you took</li><li class="flex gap-3 text-sm leading-relaxed text-foreground/85"><span class="mt-2 size-1.5 shrink-0 bg-primary" aria-hidden="true"></span>Trips with a summary of their days and distance, plus labels, frame numbers, and quick reference photos</li><li class="flex gap-3 text-sm leading-relaxed text-foreground/85"><span class="mt-2 size-1.5 shrink-0 bg-primary" aria-hidden="true"></span>GPX, CSV, and GeoJSON exports for Lightroom, darktable, or digiKam</li><li class="flex gap-3 text-sm leading-relaxed text-foreground/85"><span class="mt-2 size-1.5 shrink-0 bg-primary" aria-hidden="true"></span>Corrects for a camera clock that's drifted or set to the wrong time zone</li></ul><div class="mt-8 flex flex-wrap gap-3"><a href="https://xe1af35.github.io/hotshoe/" target="_blank" rel="noreferrer" class="group inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary bg-primary text-primary-foreground hover:bg-primary/85">Open <!-- -->Hotshoe<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-arrow-up-right size-4 transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:translate-x-0.5" aria-hidden="true"><path d="M7 7h10v10"></path><path d="M7 17 17 7"></path></svg></a><a href="https://github.com/XE1AF35/hotshoe" target="_blank" rel="noreferrer" class="group inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary border border-border text-foreground hover:border-primary hover:text-primary"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" class="size-4"><path d="M12 .3a12 12 0 0 0-3.8 23.4c.6.1.8-.3.8-.6v-2c-3.3.7-4-1.6-4-1.6-.6-1.4-1.4-1.8-1.4-1.8-1-.7.1-.7.1-.7 1.2.1 1.8 1.2 1.8 1.2 1 1.8 2.8 1.3 3.5 1 .1-.8.4-1.3.7-1.6-2.7-.3-5.5-1.3-5.5-6 0-1.2.5-2.3 1.3-3.1-.2-.4-.6-1.6 0-3.2 0 0 1-.3 3.4 1.2a11.5 11.5 0 0 1 6 0C17.3 4.7 18.3 5 18.3 5c.6 1.6.2 2.8.1 3.2.8.8 1.3 1.9 1.3 3.1 0 4.6-2.8 5.6-5.5 5.9.5.4.9 1.1.9 2.2v3.3c0 .3.2.7.8.6A12 12 0 0 0 12 .3"></path></svg>Source<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-arrow-up-right size-4 transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:translate-x-0.5" aria-hidden="true"><path d="M7 7h10v10"></path><path d="M7 17 17 7"></path></svg></a></div></div><div class="min-w-0 lg:col-span-7"><a href="https://xe1af35.github.io/hotshoe/" target="_blank" rel="noreferrer" class="viewfinder group block focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-primary"><img src="/projects/hotshoe.png?v=8e7fa59f9d" alt="Hotshoe on a phone: the last location logged with its accuracy, label, and photo; a day of entries with its map open and the trail joining them; and photos from the library being reviewed before they become entries" width="1899" height="1311" loading="lazy" class="block h-auto w-full transition-opacity duration-300 group-hover:opacity-90"/><span class="sr-only">Open <!-- -->Hotshoe</span></a></div></div></article></section><section id="principles" aria-labelledby="principles-heading" class="scroll-mt-6 border-t border-border py-16 sm:py-20"><h2 id="principles-heading" class="font-mono text-[0.7rem] uppercase tracking-[0.2em] text-primary">Principles</h2><p class="mt-5 max-w-2xl text-pretty text-2xl font-semibold tracking-tight sm:text-3xl">Every project follows the same few rules.</p><dl class="mt-10 grid gap-px bg-border sm:grid-cols-2 lg:grid-cols-4"><div class="bg-background p-6 sm:bg-card"><dt class="font-medium">Local-first</dt><dd class="mt-2 text-sm leading-relaxed text-muted-foreground">Your data lives on your device, with backups you make and keep yourself.</dd></div><div class="bg-background p-6 sm:bg-card"><dt class="font-medium">Private by default</dt><dd class="mt-2 text-sm leading-relaxed text-muted-foreground">No accounts, no analytics, and no tracking. Nothing is sent anywhere unless you send it.</dd></div><div class="bg-background p-6 sm:bg-card"><dt class="font-medium">Works offline</dt><dd class="mt-2 text-sm leading-relaxed text-muted-foreground">Once loaded, each app keeps working on a shoot with no signal, and installs like a native one.</dd></div><div class="bg-background p-6 sm:bg-card"><dt class="font-medium">Open source</dt><dd class="mt-2 text-sm leading-relaxed text-muted-foreground">Every project is MIT licensed, so you can read exactly what it does with your data.</dd></div></dl></section></main><footer class="flex flex-col gap-6 border-t border-border py-10 text-sm text-muted-foreground sm:flex-row sm:items-center sm:justify-between"><div class="space-y-2"><a href="#top" class="inline-flex items-center gap-2 font-mono text-sm font-medium tracking-[0.15em] text-foreground"><img src="/icon.png?v=8499e28e8b" alt="" width="24" height="24" class="size-6"/>XE1AF35</a><p>Made by<!-- --> <a href="https://havl-code.github.io" target="_blank" rel="noreferrer" class="text-foreground underline decoration-primary/60 underline-offset-4 transition-colors hover:text-primary">V. Ha Ly</a>. Every project is MIT licensed.</p></div><nav aria-label="Elsewhere" class="flex gap-5"><a href="https://github.com/XE1AF35" target="_blank" rel="noreferrer" class="transition-colors hover:text-foreground">GitHub</a><a href="https://havl-code.github.io" target="_blank" rel="noreferrer" class="transition-colors hover:text-foreground">Portfolio</a><a href="#top" class="transition-colors hover:text-foreground">Back to top</a></nav></footer></div><!--$--><!--/$--><script src="/_next/static/chunks/068tv5jdpv59c.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[27542,[\"/_next/static/chunks/017i2_0_yuh4o.js\"],\"default\"]\n3:I[1832,[\"/_next/static/chunks/017i2_0_yuh4o.js\"],\"default\"]\nb:I[47924,[\"/_next/static/chunks/017i2_0_yuh4o.js\"],\"default\",1]\n:HL[\"/_next/static/chunks/3-f-w91wsp8zu.css\",\"style\"]\n:HL[\"/_next/static/media/75affa71d1e2f6a7-s.p.17-aodiw50953.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/99e609270109b47d-s.p.40sczeszzbjw1.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/effe91970fc4db64-s.p.0oace-s_gkfks.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/icon.png?v=8499e28e8b\",\"image\"]\n0:{\"P\":null,\"c\":[\"\",\"\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{},\"$undefined\",\"$undefined\",4608]},\"$undefined\",\"$undefined\",4624],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/3-f-w91wsp8zu.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/017i2_0_yuh4o.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en-NZ\",\"className\":\"bg-background archivo_9443aef7-module__vKFuNW__variable ibm_plex_mono_28411002-module__cjC0Ca__variable\",\"children\":[\"$\",\"body\",null,{\"className\":\"font-sans antialiased\",\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"div\",null,{\"id\":\"top\",\"className\":\"mx-auto min-h-dvh w-full max-w-6xl px-4 sm:px-8 lg:px-12\",\"children\":[[\"$\",\"header\",null,{\"className\":\"flex items-center justify-between gap-4 border-b border-border py-5\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#top\",\"className\":\"inline-flex items-center gap-2 font-mono text-sm font-medium tracking-[0.15em] text-foreground\",\"children\":[[\"$\",\"img\",null,{\"src\":\"/icon.png?v=8499e28e8b\",\"alt\":\"\",\"width\":24,\"height\":24,\"className\":\"size-6\"}],\"XE1AF35\"]}],[\"$\",\"nav\",null,{\"aria-label\":\"Main\",\"className\":\"flex items-center gap-5 text-sm text-muted-foreground\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#projects\",\"className\":\"transition-colors hover:text-foreground\",\"children\":\"Projects\"}],[\"$\",\"a\",null,{\"href\":\"#principles\",\"className\":\"hidden transition-colors hover:text-foreground sm:inline\",\"children\":\"Principles\"}],[\"$\",\"a\",null,{\"href\":\"https://github.com/XE1AF35\",\"target\":\"_blank\",\"rel\":\"noreferrer\",\"className\":\"inline-flex items-center gap-2 transition-colors hover:text-foreground\",\"children\":[[\"$\",\"svg\",null,{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"aria-hidden\":\"true\",\"className\":\"size-4\",\"children\":[\"$\",\"path\",null,{\"d\":\"M12 .3a12 12 0 0 0-3.8 23.4c.6.1.8-.3.8-.6v-2c-3.3.7-4-1.6-4-1.6-.6-1.4-1.4-1.8-1.4-1.8-1-.7.1-.7.1-.7 1.2.1 1.8 1.2 1.8 1.2 1 1.8 2.8 1.3 3.5 1 .1-.8.4-1.3.7-1.6-2.7-.3-5.5-1.3-5.5-6 0-1.2.5-2.3 1.3-3.1-.2-.4-.6-1.6 0-3.2 0 0 1-.3 3.4 1.2a11.5 11.5 0 0 1 6 0C17.3 4.7 18.3 5 18.3 5c.6 1.6.2 2.8.1 3.2.8.8 1.3 1.9 1.3 3.1 0 4.6-2.8 5.6-5.5 5.9.5.4.9 1.1.9 2.2v3.3c0 .3.2.7.8.6A12 12 0 0 0 12 .3\"}]}],[\"$\",\"span\",null,{\"className\":\"sr-only sm:not-sr-only\",\"children\":\"GitHub\"}]]}]]}]]}],[\"$\",\"main\",null,{\"children\":[[\"$\",\"section\",null,{\"aria-labelledby\":\"tagline\",\"className\":\"py-20 sm:py-28 lg:py-36\",\"children\":[[\"$\",\"p\",null,{\"className\":\"font-mono text-[0.7rem] uppercase tracking-[0.2em] text-primary\",\"children\":[2,\" projects · Photography × software\"]}],[\"$\",\"h1\",null,{\"id\":\"tagline\",\"className\":\"mt-6 max-w-4xl text-balance text-5xl font-semibold leading-[0.95] tracking-tight sm:text-7xl lg:text-8xl\",\"children\":\"Small, local-first tools for photographers.\"}],[\"$\",\"p\",null,{\"className\":\"mt-8 max-w-2xl text-pretty text-lg leading-relaxed text-muted-foreground\",\"children\":\"Independent projects exploring where photography and software meet. Each one runs in your browser, works offline, and keeps your data on your own device.\"}],\"$L4\"]}],\"$L5\",\"$L6\"]}],\"$L7\"]}],[\"$L8\"],\"$L9\"]}],{},null,false,null]},null,false,null],\"$La\",false]],\"m\":\"$undefined\",\"G\":[\"$b\",[\"$Lc\"]],\"S\":true,\"h\":null,\"r\":\"$undefined\",\"s\":\"$undefined\",\"a\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"obdUFX2pAzzX8iZu5qidN\"}\nd:I[39612,[\"/_next/static/chunks/017i2_0_yuh4o.js\",\"/_next/static/chunks/14hf65ykvrs0z.js\"],\"default\"]\n12:I[88889,[\"/_next/static/chunks/017i2_0_yuh4o.js\"],\"OutletBoundary\"]\n13:\"$Sreact.suspense\"\n15:I[88889,[\"/_next/static/chunks/017i2_0_yuh4o.js\"],\"ViewportBoundary\"]\n17:I[88889,[\"/_next/static/chunks/017i2_0_yuh4o.js\"],\"MetadataBoundary\"]\n:HL[\"/icons/bodycap.png?v=07305f9832\",\"image\"]\n4:[\"$\",\"a\",null,{\"href\":\"#projects\",\"className\":\"group mt-10 inline-flex items-center gap-2 text-sm font-medium text-foreground transition-colors hover:text-primary\",\"children\":[\"See the projects\",[\"$\",\"$Ld\",null,{\"ref\":\"$undefined\",\"icon\":{\"name\":\"arrow-down\",\"size\":24,\"node\":[[\"path\",{\"d\":\"M12 5v14\",\"key\":\"s699le\"}],[\"path\",{\"d\":\"m19 12-7 7-7-7\",\"key\":\"1idqje\"}]]},\"className\":\"size-4 text-muted-foreground transition-transform duration-300 group-hover:translate-y-0.5 group-hover:text-primary\",\"aria-hidden\":\"true\"}]]}]\n5:[\"$\",\"section\",null,{\"id\":\"projects\",\"aria-labelledby\":\"projects-heading\",\"className\":\"scroll-mt-6\",\"children\":[[\"$\",\"h2\",null,{\"id\":\"projects-heading\",\"className\":\"font-mono text-[0.7rem] uppercase tracking-[0.2em] pb-6 text-primary\",\"children\":\"Projects\"}],[[\"$\",\"article\",\"Bodycap\",{\"aria-labelledby\":\"bodycap\",\"className\":\"border-t border-border py-16 sm:py-20\",\"children\":[\"$\",\"div\",null,{\"className\":\"grid grid-cols-1 gap-10 lg:grid-cols-12 lg:gap-14\",\"children\":[[\"$\",\"div\",null,{\"className\":\"min-w-0 lg:col-span-5\",\"children\":[[\"$\",\"p\",null,{\"className\":\"font-mono text-[0.7rem] uppercase tracking-[0.2em] text-muted-foreground\",\"children\":[[\"$\",\"span\",null,{\"className\":\"text-primary\",\"children\":\"01\"}],[[\"$\",\"span\",\"Web app\",{\"children\":[\" · \",\"Web app\"]}],[\"$\",\"span\",\"Any device\",{\"children\":[\" · \",\"Any device\"]}],[\"$\",\"span\",\"Works offline\",{\"children\":[\" · \",\"Works offline\"]}]]]}],[\"$\",\"h3\",null,{\"id\":\"bodycap\",\"className\":\"mt-5 flex items-center gap-4 text-4xl font-semibold tracking-tight sm:text-5xl\",\"children\":[[\"$\",\"img\",null,{\"src\":\"/icons/bodycap.png?v=07305f9832\",\"alt\":\"\",\"width\":48,\"height\":48,\"className\":\"size-10 shrink-0 sm:size-12\"}],\"Bodycap\"]}],[\"$\",\"p\",null,{\"className\":\"mt-3 text-xl text-foreground/90\",\"children\":\"Your camera gear, organised.\"}],[\"$\",\"p\",null,{\"className\":\"mt-5 text-pretty leading-relaxed text-muted-foreground\",\"children\":\"Keep track of every body, lens, flash, and bag you own, with serial numbers, what you paid, warranties, and where it all is. It never needs an account.\"}],[\"$\",\"ul\",null,{\"className\":\"mt-6 space-y-3\",\"children\":[[\"$\",\"li\",\"Suggests models as you type, from a built-in catalogue of camera bodies and lenses, and fills in their specs\",{\"className\":\"flex gap-3 text-sm leading-relaxed text-foreground/85\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 size-1.5 shrink-0 bg-primary\",\"aria-hidden\":\"true\"}],\"Suggests models as you type, from a built-in catalogue of camera bodies and lenses, and fills in their specs\"]}],[\"$\",\"li\",\"Kits that double as packing checklists, and can be shared as a link\",{\"className\":\"flex gap-3 text-sm leading-relaxed text-foreground/85\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 size-1.5 shrink-0 bg-primary\",\"aria-hidden\":\"true\"}],\"Kits that double as packing checklists, and can be shared as a link\"]}],[\"$\",\"li\",\"A log of shoots, showing how often each item is used and what has sat unused\",{\"className\":\"flex gap-3 text-sm leading-relaxed text-foreground/85\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 size-1.5 shrink-0 bg-primary\",\"aria-hidden\":\"true\"}],\"A log of shoots, showing how often each item is used and what has sat unused\"]}],[\"$\",\"li\",\"What you spend each year, and what your gear is worth now\",{\"className\":\"flex gap-3 text-sm leading-relaxed text-foreground/85\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 size-1.5 shrink-0 bg-primary\",\"aria-hidden\":\"true\"}],\"What you spend each year, and what your gear is worth now\"]}],[\"$\",\"li\",\"Loans, a maintenance log, and an insurance list ready to print\",{\"className\":\"flex gap-3 text-sm leading-relaxed text-foreground/85\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 size-1.5 shrink-0 bg-primary\",\"aria-hidden\":\"true\"}],\"Loans, a maintenance log, and an insurance list ready to print\"]}],[\"$\",\"li\",\"Which lenses fit which cameras, with a map of your whole system\",{\"className\":\"flex gap-3 text-sm leading-relaxed text-foreground/85\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 size-1.5 shrink-0 bg-primary\",\"aria-hidden\":\"true\"}],\"Which lenses fit which cameras, with a map of your whole system\"]}]]}],[\"$\",\"div\",null,{\"className\":\"mt-8 flex flex-wrap gap-3\",\"children\":[[\"$\",\"a\",null,{\"href\":\"https://xe1af35.github.io/bodycap/\",\"target\":\"_blank\",\"rel\":\"noreferrer\",\"className\":\"group inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary bg-primary text-primary-foreground hover:bg-primary/85\",\"children\":[[\"Open \",\"Bodycap\"],\"$Le\"]}],\"$Lf\"]}]]}],\"$L10\"]}]}],\"$L11\"]]}]\n6:[\"$\",\"section\",null,{\"id\":\"principles\",\"aria-labelledby\":\"principles-heading\",\"className\":\"scroll-mt-6 border-t border-border py-16 sm:py-20\",\"children\":[[\"$\",\"h2\",null,{\"id\":\"principles-heading\",\"className\":\"font-mono text-[0.7rem] uppercase tracking-[0.2em] text-primary\",\"children\":\"Principles\"}],[\"$\",\"p\",null,{\"className\":\"mt-5 max-w-2xl text-pretty text-2xl font-semibold tracking-tight sm:text-3xl\",\"children\":\"Every project follows the same few rules.\"}],[\"$\",\"dl\",null,{\"className\":\"mt-10 grid gap-px bg-border sm:grid-cols-2 lg:grid-cols-4\",\"children\":[[\"$\",\"div\",\"Local-first\",{\"className\":\"bg-background p-6 sm:bg-card\",\"children\":[[\"$\",\"dt\",null,{\"className\":\"font-medium\",\"children\":\"Local-first\"}],[\"$\",\"dd\",null,{\"className\":\"mt-2 text-sm leading-relaxed text-muted-foreground\",\"children\":\"Your data lives on your device, with backups you make and keep yourself.\"}]]}],[\"$\",\"div\",\"Private by default\",{\"className\":\"bg-background p-6 sm:bg-card\",\"children\":[[\"$\",\"dt\",null,{\"className\":\"font-medium\",\"children\":\"Private by default\"}],[\"$\",\"dd\",null,{\"className\":\"mt-2 text-sm leading-relaxed text-muted-foreground\",\"children\":\"No accounts, no analytics, and no tracking. Nothing is sent anywhere unless you send it.\"}]]}],[\"$\",\"div\",\"Works offline\",{\"className\":\"bg-background p-6 sm:bg-card\",\"children\":[[\"$\",\"dt\",null,{\"className\":\"font-medium\",\"children\":\"Works offline\"}],[\"$\",\"dd\",null,{\"className\":\"mt-2 text-sm leading-relaxed text-muted-foreground\",\"children\":\"Once loaded, each app keeps working on a shoot with no signal, and installs like a native one.\"}]]}],[\"$\",\"div\",\"Open source\",{\"className\":\"bg-background p-6 sm:bg-card\",\"children\":[[\"$\",\"dt\",null,{\"className\":\"font-medium\",\"children\":\"Open source\"}],[\"$\",\"dd\",null,{\"className\":\"mt-2 text-sm leading-relaxed text-muted-foreground\",\"children\":\"Every project is MIT licensed, so you can read exactly what it does with your data.\"}]]}]]}]]}]\n7:[\"$\",\"footer\",null,{\"className\":\"flex flex-col gap-6 border-t border-border py-10 text-sm text-muted-foreground sm:flex-row sm:items-center sm:justify-between\",\"children\":[[\"$\",\"div\",null,{\"className\":\"space-y-2\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#top\",\"className\":\"inline-flex items-center gap-2 font-mono text-sm font-medium tracking-[0.15em] text-foreground\",\"children\":[[\"$\",\"img\",null,{\"src\":\"/icon.png?v=8499e28e8b\",\"alt\":\"\",\"width\":24,\"height\":24,\"className\":\"size-6\"}],\"XE1AF35\"]}],[\"$\",\"p\",null,{\"children\":[\"Made by\",\" \",[\"$\",\"a\",null,{\"href\":\"https://havl-code.github.io\",\"target\":\"_blank\",\"rel\":\"noreferrer\",\"className\":\"text-foreground underline decoration-primary/60 underline-offset-4 transition-colors hover:text-primary\",\"children\":\"V. Ha Ly\"}],\". Every project is MIT licensed.\"]}]]}],[\"$\",\"nav\",null,{\"aria-label\":\"Elsewhere\",\"className\":\"flex gap-5\",\"children\":[[\"$\",\"a\",null,{\"href\":\"https://github.com/XE1AF35\",\"target\":\"_blank\",\"rel\":\"noreferrer\",\"className\":\"transition-colors hover:text-foreground\",\"children\":\"GitHub\"}],[\"$\",\"a\",null,{\"href\":\"https://havl-code.github.io\",\"target\":\"_blank\",\"rel\":\"noreferrer\",\"className\":\"transition-colors hover:text-foreground\",\"children\":\"Portfolio\"}],[\"$\",\"a\",null,{\"href\":\"#top\",\"className\":\"transition-colors hover:text-foreground\",\"children\":\"Back to top\"}]]}]]}]\n8:[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/14hf65ykvrs0z.js\",\"async\":true,\"nonce\":\"$undefined\"}]\n9:[\"$\",\"$L12\",null,{\"children\":[\"$\",\"$13\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@14\"}]}]\na:[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L15\",null,{\"children\":\"$L16\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L17\",null,{\"children\":[\"$\",\"$13\",null,{\"name\":\"Next.Metadata\",\"children\":\"$L18\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}]\nc:[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/3-f-w91wsp8zu.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]\n:HL[\"/projects/bodycap.png?v=59fda9c60c\",\"image\"]\n:HL[\"/icons/hotshoe.png?v=82505950b6\",\"image\"]\ne:[\"$\",\"$Ld\",null,{\"ref\":\"$undefined\",\"icon\":{\"name\":\"arrow-up-right\",\"size\":24,\"node\":[[\"path\",{\"d\":\"M7 7h10v10\",\"key\":\"1tivn9\"}],[\"path\",{\"d\":\"M7 17 17 7\",\"key\":\"1vkiza\"}]]},\"className\":\"size-4 transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:translate-x-0.5\",\"aria-hidden\":\"true\"}]\nf:[\"$\",\"a\",null,{\"href\":\"https://github.com/XE1AF35/bodycap\",\"target\":\"_blank\",\"rel\":\"noreferrer\",\"className\":\"group inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary border border-border text-foreground hover:border-primary hover:text-primary\",\"children\":[[[\"$\",\"svg\",null,{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"aria-hidden\":\"true\",\"className\":\"size-4\",\"children\":[\"$\",\"path\",null,{\"d\":\"M12 .3a12 12 0 0 0-3.8 23.4c.6.1.8-.3.8-.6v-2c-3.3.7-4-1.6-4-1.6-.6-1.4-1.4-1.8-1.4-1.8-1-.7.1-.7.1-.7 1.2.1 1.8 1.2 1.8 1.2 1 1.8 2.8 1.3 3.5 1 .1-.8.4-1.3.7-1.6-2.7-.3-5.5-1.3-5.5-6 0-1.2.5-2.3 1.3-3.1-.2-.4-.6-1.6 0-3.2 0 0 1-.3 3.4 1.2a11.5 11.5 0 0 1 6 0C17.3 4.7 18.3 5 18.3 5c.6 1.6.2 2.8.1 3.2.8.8 1.3 1.9 1.3 3.1 0 4.6-2.8 5.6-5.5 5.9.5.4.9 1.1.9 2.2v3.3c0 .3.2.7.8.6A12 12 0 0 0 12 .3\"}]}],\"Source\"],[\"$\",\"$Ld\",null,{\"ref\":\"$undefined\",\"icon\":\"$e:props:icon\",\"className\":\"size-4 transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:translate-x-0.5\",\"aria-hidden\":\"true\"}]]}]\n10:[\"$\",\"div\",null,{\"className\":\"min-w-0 lg:col-span-7\",\"children\":[\"$\",\"a\",null,{\"href\":\"https://xe1af35.github.io/bodycap/\",\"target\":\"_blank\",\"rel\":\"noreferrer\",\"className\":\"viewfinder group block focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-primary\",\"children\":[[\"$\",\"img\",null,{\"src\":\"/projects/bodycap.png?v=59fda9c60c\",\"alt\":\"The Bodycap dashboard, with a warranty running out, gear counts, a camera on loan, what the gear is worth by category, and backup status\",\"width\":1320,\"height\":960,\"loading\":\"eager\",\"className\":\"block h-auto w-full transition-opacity duration-300 group-hover:opacity-90\"}],[\"$\",\"span\",null,{\"className\":\"sr-only\",\"children\":[\"Open \",\"Bodycap\"]}]]}]}]\n11:[\"$\",\"article\",\"Hotshoe\",{\"aria-labelledby\":\"hotshoe\",\"className\":\"border-t border-border py-16 sm:py-20\",\"children\":[\"$\",\"div\",null,{\"className\":\"grid grid-cols-1 gap-10 lg:grid-cols-12 lg:gap-14\",\"children\":[[\"$\",\"div\",null,{\"className\":\"min-w-0 lg:col-span-5\",\"children\":[[\"$\",\"p\",null,{\"className\":\"font-mono text-[0.7rem] uppercase tracking-[0.2em] text-muted-foreground\",\"children\":[[\"$\",\"span\",null,{\"className\":\"text-primary\",\"children\":\"02\"}],[[\"$\",\"span\",\"iPhone\",{\"children\":[\" · \",\"iPhone\"]}],[\"$\",\"span\",\"Home Screen app\",{\"children\":[\" · \",\"Home Screen app\"]}],[\"$\",\"span\",\"Works offline\",{\"children\":[\" · \",\"Works offline\"]}]]]}],[\"$\",\"h3\",null,{\"id\":\"hotshoe\",\"className\":\"mt-5 flex items-center gap-4 text-4xl font-semibold tracking-tight sm:text-5xl\",\"children\":[[\"$\",\"img\",null,{\"src\":\"/icons/hotshoe.png?v=82505950b6\",\"alt\":\"\",\"width\":48,\"height\":48,\"className\":\"size-10 shrink-0 sm:size-12\"}],\"Hotshoe\"]}],[\"$\",\"p\",null,{\"className\":\"mt-3 text-xl text-foreground/90\",\"children\":\"Where you took the photo, in one tap.\"}],[\"$\",\"p\",null,{\"className\":\"mt-5 text-pretty leading-relaxed text-muted-foreground\",\"children\":\"Log your location as you shoot, then geotag your photos later. It's made for cameras that don't record where a photo was taken.\"}],[\"$\",\"ul\",null,{\"className\":\"mt-6 space-y-3\",\"children\":[[\"$\",\"li\",\"Waits for an accurate fix, and marks the ones that fall short\",{\"className\":\"flex gap-3 text-sm leading-relaxed text-foreground/85\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 size-1.5 shrink-0 bg-primary\",\"aria-hidden\":\"true\"}],\"Waits for an accurate fix, and marks the ones that fall short\"]}],[\"$\",\"li\",\"Adds entries from photos already in your library, using their own time and location\",{\"className\":\"flex gap-3 text-sm leading-relaxed text-foreground/85\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 size-1.5 shrink-0 bg-primary\",\"aria-hidden\":\"true\"}],\"Adds entries from photos already in your library, using their own time and location\"]}],[\"$\",\"li\",\"A map of each day's entries, with a trail showing the route you took\",{\"className\":\"flex gap-3 text-sm leading-relaxed text-foreground/85\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 size-1.5 shrink-0 bg-primary\",\"aria-hidden\":\"true\"}],\"A map of each day's entries, with a trail showing the route you took\"]}],[\"$\",\"li\",\"Trips with a summary of their days and distance, plus labels, frame numbers, and quick reference photos\",{\"className\":\"flex gap-3 text-sm leading-relaxed text-foreground/85\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 size-1.5 shrink-0 bg-primary\",\"aria-hidden\":\"true\"}],\"Trips with a summary of their days and distance, plus labels, frame numbers, and quick reference photos\"]}],[\"$\",\"li\",\"GPX, CSV, and GeoJSON exports for Lightroom, darktable, or digiKam\",{\"className\":\"flex gap-3 text-sm leading-relaxed text-foreground/85\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 size-1.5 shrink-0 bg-primary\",\"aria-hidden\":\"true\"}],\"GPX, CSV, and GeoJSON exports for Lightroom, darktable, or digiKam\"]}],[\"$\",\"li\",\"Corrects for a camera clock that's drifted or set to the wrong time zone\",{\"className\":\"flex gap-3 text-sm leading-relaxed text-foreground/85\",\"children\":[[\"$\",\"span\",null,{\"className\":\"mt-2 size-1.5 shrink-0 bg-primary\",\"aria-hidden\":\"true\"}],\"Corrects for a camera clock that's drifted or set to the wrong time zone\"]}]]}],[\"$\",\"div\",null,{\"className\":\"mt-8 flex flex-wrap gap-3\",\"children\":[[\"$\",\"a\",null,{\"href\":\"https://xe1af35.github.io/hotshoe/\",\"target\":\"_blank\",\"rel\":\"noreferrer\",\"className\":\"group inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary bg-primary text-primary-foreground hover:bg-primary/85\",\"children\":[[\"Open \",\"Hotshoe\"],[\"$\",\"$Ld\",null,{\"ref\":\"$undefined\",\"icon\":\"$e:props:icon\",\"className\":\"size-4 transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:translate-x-0.5\",\"aria-hidden\":\"true\"}]]}],\"$L19\"]}]]}],\"$L1a\"]}]}]\n19:[\"$\",\"a\",null,{\"href\":\"https://github.com/XE1AF35/hotshoe\",\"target\":\"_blank\",\"rel\":\"noreferrer\",\"className\":\"group inline-flex items-center gap-2 px-4 py-2.5 text-sm font-medium transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary border border-border text-foreground hover:border-primary hover:text-primary\",\"children\":[[[\"$\",\"svg\",null,{\"viewBox\":\"0 0 24 24\",\"fill\":\"currentColor\",\"aria-hidden\":\"true\",\"className\":\"size-4\",\"children\":[\"$\",\"path\",null,{\"d\":\"M12 .3a12 12 0 0 0-3.8 23.4c.6.1.8-.3.8-.6v-2c-3.3.7-4-1.6-4-1.6-.6-1.4-1.4-1.8-1.4-1.8-1-.7.1-.7.1-.7 1.2.1 1.8 1.2 1.8 1.2 1 1.8 2.8 1.3 3.5 1 .1-.8.4-1.3.7-1.6-2.7-.3-5.5-1.3-5.5-6 0-1.2.5-2.3 1.3-3.1-.2-.4-.6-1.6 0-3.2 0 0 1-.3 3.4 1.2a11.5 11.5 0 0 1 6 0C17.3 4.7 18.3 5 18.3 5c.6 1.6.2 2.8.1 3.2.8.8 1.3 1.9 1.3 3.1 0 4.6-2.8 5.6-5.5 5.9.5.4.9 1.1.9 2.2v3.3c0 .3.2.7.8.6A12 12 0 0 0 12 .3\"}]}],\"Source\"],[\"$\",\"$Ld\",null,{\"ref\":\"$undefined\",\"icon\":\"$e:props:icon\",\"className\":\"size-4 transition-transform duration-300 group-hover:-translate-y-0.5 group-hover:translate-x-0.5\",\"aria-hidden\":\"true\"}]]}]\n1a:[\"$\",\"div\",null,{\"className\":\"min-w-0 lg:col-span-7\",\"children\":[\"$\",\"a\",null,{\"href\":\"https://xe1af35.github.io/hotshoe/\",\"target\":\"_blank\",\"rel\":\"noreferrer\",\"className\":\"viewfinder group block focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-primary\",\"children\":[[\"$\",\"img\",null,{\"src\":\"/projects/hotshoe.png?v=8e7fa59f9d\",\"alt\":\"Hotshoe on a phone: the last location logged with its accuracy, label, and photo; a day of entries with its map open and the trail joining them; and photos from the library being reviewed before they become entries\",\"width\":1899,\"height\":1311,\"loading\":\"lazy\",\"className\":\"block h-auto w-full transition-opacity duration-300 group-hover:opacity-90\"}],[\"$\",\"span\",null,{\"className\":\"sr-only\",\"children\":[\"Open \",\"Hotshoe\"]}]]}]}]\n16:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"2\",{\"name\":\"theme-color\",\"content\":\"#0f0e0d\"}],[\"$\",\"meta\",\"3\",{\"name\":\"color-scheme\",\"content\":\"dark\"}]]\n1b:I[87459,[\"/_next/static/chunks/017i2_0_yuh4o.js\"],\"IconMark\"]\n14:null\n18:[[\"$\",\"title\",\"0\",{\"children\":\"XE1AF35: Small, local-first tools for photographers\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Independent projects exploring where photography and software meet. Each one runs in your browser, works offline, and keeps your data on your own device.\"}],[\"$\",\"link\",\"2\",{\"rel\":\"icon\",\"href\":\"/icon.png?icon.20_jeyolqkyei.png\",\"sizes\":\"100x100\",\"type\":\"image/png\"}],[\"$\",\"link\",\"3\",{\"rel\":\"apple-touch-icon\",\"href\":\"/apple-icon.png?apple-icon.3x8few6mnfmg3.png\",\"sizes\":\"180x180\",\"type\":\"image/png\"}],[\"$\",\"$L1b\",\"4\",{}]]\n"])</script></body></html>