1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <meta name="description" content="Get in touch with Opes at opes.dev."> 7 <meta name="theme-color" content="#0a0a0a"> 8 <link rel="preconnect" href="https://challenges.cloudflare.com" crossorigin> 9 <meta property="og:type" content="website"> 10 <meta property="og:title" content="Contact :: Opes.dev"> 11 <meta property="og:description" content="Get in touch with Opes at opes.dev."> 12 <meta property="og:url" content="https://opes.dev/contact"> 13 <link rel="canonical" href="https://opes.dev/contact"> 14 <meta property="og:site_name" content="opes.dev"> 15 <meta property="og:image" content="https://opes.dev/assets/images/brand/og.png"> 16 <meta property="og:image:width" content="1200"> 17 <meta property="og:image:height" content="630"> 18 <meta property="og:image:alt" content="Opes.dev"> 19 <meta name="twitter:card" content="summary_large_image"> 20 <meta name="twitter:title" content="Contact :: Opes.dev"> 21 <meta name="twitter:description" content="Get in touch with Opes at opes.dev."> 22 <meta name="twitter:image" content="https://opes.dev/assets/images/brand/og.png"> 23 <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://challenges.cloudflare.com; style-src 'self'; font-src 'self'; img-src 'self' data:; connect-src 'self'; frame-src 'self' https://challenges.cloudflare.com; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests"> 24 <link rel="icon" href="/assets/images/brand/favicon.svg" type="image/svg+xml"> 25 <title>Contact :: Opes.dev</title> 26 <link rel="preload" href="/assets/fonts/fredoka-600.woff2" as="font" type="font/woff2" crossorigin> 27 <link rel="stylesheet" href="/assets/css/bundle.css?v=1787580896"> 28
28<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
28 29
29<script type="application/ld+json">{"@context":"https://schema.org","@graph":[{"@type":"Person","name":"Opes","alternateName":"Dani","url":"https://opes.dev/","sameAs":["https://github.com/opesoid"]},{"@type":"WebSite","name":"opes.dev","url":"https://opes.dev/","description":"Building websites, scripts, tools and extensions in my spare time. Check out my work or drop me a message at opes.dev."},{"@type":"ContactPoint","contactType":"customer support","email":"[email protected]","url":"https://opes.dev/contact","availableLanguage":"English"},{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://opes.dev/"},{"@type":"ListItem","position":2,"name":"Contact","item":"https://opes.dev/contact"}]}]}</script>
29 30</head> 31<body> 32 33<a class="skip-link absolute top-[-100%] left-0 z-[100] bg-accent px-3 py-[0.4rem] font-body text-[13px] text-bg no-underline focus:top-0" href="#main-content">skip to content</a> 34 35 36<div class="mobile-nav fixed inset-0 z-[200] overflow-hidden touch-none" id="mobile-nav" hidden aria-hidden="true"> 37 <button type="button" class="mobile-nav__backdrop absolute inset-0 m-0 cursor-pointer border-0 bg-black/55 p-0 opacity-0 transition-opacity duration-200 ease-in-out" aria-label="Close menu"></button> 38 <div class="mobile-nav__panel absolute top-0 right-0 h-dvh w-[min(18rem,88vw)] overflow-y-auto border-l border-border bg-[rgba(12,12,12,0.97)] pt-[5.5rem] pr-6 pb-8 pl-6 shadow-[-12px_0_40px_rgba(0,0,0,0.45)] backdrop-blur-[18px] transition-transform duration-300 ease-in-out translate-x-full touch-pan-y" role="dialog" aria-modal="true" aria-label="Main navigation"> 39 <nav class="mobile-nav__nav block" aria-label="Main navigation"> 40 <ul class="site-nav__list mobile-nav__list flex list-none flex-col items-stretch gap-[0.35rem] m-0 p-0"><li class="site-nav__item m-0"><a href="/" class="site-nav__link inline-flex min-h-9 items-center rounded-full px-[0.85rem] py-[0.35rem] font-body text-[13px] tracking-[0.02em] text-dim no-underline transition-colors duration-200 hover:bg-white/5 hover:text-fg min-h-11 rounded-[10px] px-4 py-[0.65rem] text-[15px]">Home</a></li><li class="site-nav__item m-0"><a href="/about" class="site-nav__link inline-flex min-h-9 items-center rounded-full px-[0.85rem] py-[0.35rem] font-body text-[13px] tracking-[0.02em] text-dim no-underline transition-colors duration-200 hover:bg-white/5 hover:text-fg min-h-11 rounded-[10px] px-4 py-[0.65rem] text-[15px]">About</a></li><li class="site-nav__item m-0"><a href="/projects" class="site-nav__link inline-flex min-h-9 items-center rounded-full px-[0.85rem] py-[0.35rem] font-body text-[13px] tracking-[0.02em] text-dim no-underline transition-colors duration-200 hover:bg-white/5 hover:text-fg min-h-11 rounded-[10px] px-4 py-[0.65rem] text-[15px]">Projects</a></li><li class="site-nav__item m-0"><a href="/services" class="site-nav__link inline-flex min-h-9 items-center rounded-full px-[0.85rem] py-[0.35rem] font-body text-[13px] tracking-[0.02em] text-dim no-underline transition-colors duration-200 hover:bg-white/5 hover:text-fg min-h-11 rounded-[10px] px-4 py-[0.65rem] text-[15px]">Services</a></li><li class="site-nav__item m-0"><a href="/donate" class="site-nav__link inline-flex min-h-9 items-center rounded-full px-[0.85rem] py-[0.35rem] font-body text-[13px] tracking-[0.02em] text-dim no-underline transition-colors duration-200 hover:bg-white/5 hover:text-fg min-h-11 rounded-[10px] px-4 py-[0.65rem] text-[15px]">Donate</a></li><li class="site-nav__item m-0"><a href="/contact" class="site-nav__link inline-flex min-h-9 items-center rounded-full px-[0.85rem] py-[0.35rem] font-body text-[13px] tracking-[0.02em] text-dim no-underline transition-colors duration-200 hover:bg-white/5 hover:text-fg site-nav__link--active bg-accent/12 text-accent hover:bg-accent/16 hover:text-accent min-h-11 rounded-[10px] px-4 py-[0.65rem] text-[15px]" aria-current="page">Contact</a></li></ul> </nav> 41 </div> 42</div> 43 44<div class="wrapper relative z-[1] mx-auto max-w-site px-8 py-12 max-[600px]:px-5 max-[600px]:py-8"> 45 46 <header class="site-masthead sticky top-0 z-[100] mb-10 pt-1" data-masthead> 47 <div class="site-masthead__bar flex items-center justify-between gap-5 rounded-[14px] border border-border bg-[rgba(10,10,10,0.55)] px-[0.85rem] py-[0.65rem] backdrop-blur-[10px] transition-[background-color,border-color,box-shadow] duration-200 ease-in-out"> 48 <a href="/" class="site-masthead__brand shrink-0 pb-[0.1rem] font-brand text-[1.65rem] font-semibold leading-none tracking-[-0.01em] text-fg no-underline hover:bg-transparent hover:text-accent hover:shadow-none">Opes.dev</a> 49 50 <button type="button" 51 class="nav-toggle relative z-[202] hidden size-11 cursor-pointer items-center justify-center rounded-[10px] border border-border bg-white/[0.03] p-0 text-fg transition-colors duration-200 hover:border-accent/35 hover:bg-white/[0.06] max-[720px]:inline-flex" 52 aria-expanded="false" 53 aria-controls="mobile-nav" 54 aria-label="Open menu">
55 <span class="nav-toggle__lines" aria-hidden="true"></span> 56 </button> 57 58 <nav id="site-nav" class="site-nav site-nav--desktop flex items-center gap-[0.35rem] max-[720px]:hidden" aria-label="Main navigation"> 59 <ul class="site-nav__list m-0 flex list-none flex-wrap items-center gap-[0.2rem] p-0"><li class="site-nav__item m-0"><a href="/" class="site-nav__link inline-flex min-h-9 items-center rounded-full px-[0.85rem] py-[0.35rem] font-body text-[13px] tracking-[0.02em] text-dim no-underline transition-colors duration-200 hover:bg-white/5 hover:text-fg">Home</a></li><li class="site-nav__item m-0"><a href="/about" class="site-nav__link inline-flex min-h-9 items-center rounded-full px-[0.85rem] py-[0.35rem] font-body text-[13px] tracking-[0.02em] text-dim no-underline transition-colors duration-200 hover:bg-white/5 hover:text-fg">About</a></li><li class="site-nav__item m-0"><a href="/projects" class="site-nav__link inline-flex min-h-9 items-center rounded-full px-[0.85rem] py-[0.35rem] font-body text-[13px] tracking-[0.02em] text-dim no-underline transition-colors duration-200 hover:bg-white/5 hover:text-fg">Projects</a></li><li class="site-nav__item m-0"><a href="/services" class="site-nav__link inline-flex min-h-9 items-center rounded-full px-[0.85rem] py-[0.35rem] font-body text-[13px] tracking-[0.02em] text-dim no-underline transition-colors duration-200 hover:bg-white/5 hover:text-fg">Services</a></li><li class="site-nav__item m-0"><a href="/donate" class="site-nav__link inline-flex min-h-9 items-center rounded-full px-[0.85rem] py-[0.35rem] font-body text-[13px] tracking-[0.02em] text-dim no-underline transition-colors duration-200 hover:bg-white/5 hover:text-fg">Donate</a></li><li class="site-nav__item m-0"><a href="/contact" class="site-nav__link inline-flex min-h-9 items-center rounded-full px-[0.85rem] py-[0.35rem] font-body text-[13px] tracking-[0.02em] text-dim no-underline transition-colors duration-200 hover:bg-white/5 hover:text-fg site-nav__link--active bg-accent/12 text-accent hover:bg-accent/16 hover:text-accent" aria-current="page">Contact</a></li></ul> </nav> 60</div> 61 </header> 62 63<main id="main-content"> 64 65 <h1 class="sr-only absolute m-[-1px] h-px w-px overflow-hidden whitespace-nowrap border-0 p-0 [clip-path:inset(50%)]">contact</h1> 66 67 <section class="section mb-10" id="contact"> 68 <div class="grid grid-cols-1 items-start gap-6 min-[601px]:grid-cols-2 min-[601px]:gap-8"> 69 <div class="retro-window border border-border bg-white/[0.02]" id="contact-form"><div class="retro-window__chrome flex items-center gap-[5px] border-b border-border px-[0.9rem] py-2 max-[600px]:pl-4" aria-hidden="true"><span class="retro-window__dot inline-block size-2.5 shrink-0 rounded-full opacity-80 bg-traffic-close"></span><span class="retro-window__dot inline-block size-2.5 shrink-0 rounded-full opacity-80 bg-traffic-min"></span><span class="retro-window__dot inline-block size-2.5 shrink-0 rounded-full opacity-80 bg-traffic-max"></span></div><h2 class="panel__heading m-0 px-5 pt-[0.85rem] font-normal text-[13px] lowercase tracking-[0.1em] text-accent max-[600px]:pl-4">Send a message</h2><div class="retro-window__body p-5 px-6 max-[600px]:p-4"> <div class="stack"> 70 <p class="text-dim">Usually reply within 24â48 hours.</p> 71 72 73 <form class="flex max-w-lg flex-col gap-4" action="/contact" method="POST" data-disable-on-submit> 74 <input type="hidden" name="_csrf" value="fb3efb72ce645da7aa5bbb6d1412c570d541e7b7901cb7d6940b346082f46ae0"> 75 76 <div class="absolute left-[-9999px] h-px w-px overflow-hidden" aria-hidden="true"> 77 <label for="website">website</label> 78 <input type="text" id="website" name="website" tabindex="-1" autocomplete="off"> 79 </div> 80 81 <div class="flex flex-col gap-[0.35rem]"> 82 <label for="name" class="text-xs uppercase tracking-[0.1em] text-dim">name</label> 83 <input type="text" id="name" name="name" class="border border-border bg-bg px-3 py-[0.6rem] font-body text-base text-fg focus:border-accent focus:outline-2 focus:outline-offset-0 focus:outline-accent" required autocomplete="name" maxlength="120"> 84 </div> 85 86 <div class="flex flex-col gap-[0.35rem]"> 87 <label for="email" class="text-xs uppercase tracking-[0.1em] text-dim">email</label> 88 <input type="email" id="email" name="email" class="border border-border bg-bg px-3 py-[0.6rem] font-body text-base text-fg focus:border-accent focus:outline-2 focus:outline-offset-0 focus:outline-accent" required autocomplete="email" maxlength="254"> 89 </div> 90 91 <div class="flex flex-col gap-[0.35rem]"> 92 <label for="subject" class="text-xs uppercase tracking-[0.1em] text-dim">subject <span class="text-dim">(optional)</span></label> 93 <input type="text" id="subject" name="subject" class="border border-border bg-bg px-3 py-[0.6rem] font-body text-base text-fg focus:border-accent focus:outline-2 focus:outline-offset-0 focus:outline-accent" autocomplete="off" maxlength="200"> 94 </div> 95 96 <div class="flex flex-col gap-[0.35rem]"> 97 <label for="message" class="text-xs uppercase tracking-[0.1em] text-dim">message</label> 98 <textarea id="message" name="message" rows="6" class="border border-border bg-bg px-3 py-[0.6rem] font-body text-base text-fg focus:border-accent focus:outline-2 focus:outline-offset-0 focus:outline-accent resize-y" required maxlength="5000"></textarea> 99 </div> 100 101 <div class="flex flex-col gap-[0.35rem] min-h-[65px]"> 102 <div class="cf-turnstile" data-sitekey="0x4AAAAAAD5Q1HK0P63CPb9A"></div> 103 </div> 104 105 <button type="submit" class="inline-block cursor-pointer border border-border bg-transparent px-4 py-2 font-body text-[13px] lowercase tracking-[0.06em] text-fg no-underline transition-colors hover:bg-white/[0.04] hover:text-fg hover:shadow-none active:translate-y-
105px disabled:cursor-not-allowed disabled:opacity-60 max-[640px]:min-h-11 max-[640px]:px-[1.1rem] max-[640px]:py-[0.65rem] max-[640px]:text-sm border-accent bg-accent/[0.06] text-accent hover:bg-accent/10 hover:text-accent hover:shadow-glow active:bg-accent/[0.04]">send message</button> 106 </form> 107 108 <p class="text-[13px] text-dim">Your message is handled per our <a href="/privacy">privacy policy</a> and <a href="/cookies">cookie policy</a>.</p> 109 </div> 110 </div></div> 111 <div class="flex flex-col gap-6"> 112 <div class="retro-window border border-border bg-white/[0.02]" id="contact-info"><div class="retro-window__chrome flex items-center gap-[5px] border-b border-border px-[0.9rem] py-2 max-[600px]:pl-4" aria-hidden="true"><span class="retro-window__dot inline-block size-2.5 shrink-0 rounded-full opacity-80 bg-traffic-close"></span><span class="retro-window__dot inline-block size-2.5 shrink-0 rounded-full opacity-80 bg-traffic-min"></span><span class="retro-window__dot inline-block size-2.5 shrink-0 rounded-full opacity-80 bg-traffic-max"></span></div><h2 class="panel__heading m-0 px-5 pt-[0.85rem] font-normal text-[13px] lowercase tracking-[0.1em] text-accent max-[600px]:pl-4">Direct contact</h2><div class="retro-window__body p-5 px-6 max-[600px]:p-4"> <dl class="m-0 grid grid-cols-[7rem_1fr] gap-x-0 gap-y-3 max-[640px]:grid-cols-1 max-[640px]:gap-y-1"> 113 <dt class="text-sm text-dim max-[640px]:mt-2">email</dt> 114 <dd class="m-0 text-sm"><a href="/cdn-cgi/l/email-protection#d3a0a6a3a3bca1a793bca3b6a0fdb7b6a5"><span class="__cf_email__" data-cfemail="a2d1d7d2d2cdd0d6e2cdd2c7d18cc6c7d4">[email protected]</span></a></dd> 115 116 <dt class="text-sm text-dim max-[640px]:mt-2">github</dt> 117 <dd class="m-0 text-sm"> 118 <a href="https://github.com/opesoid" target="_blank" rel="noopener noreferrer" aria-label="GitHub profile (opens in new tab)"> 119 github.com/opesoid 120 </a> 121 </dd> 122 </dl> 123 </div></div> </div> 124 </div> 125 </section> 126 127</main> 128 129 130 <footer class="site-footer mt-16 border-t border-border pt-6"> 131 <p class="site-footer__copy m-0 text-[13px] text-dim">© 2026 <a href="/">opes.dev</a> · <a href="/privacy">privacy</a> · <a href="/cookies">cookies</a> · <a href="/terms">terms</a> · <a href="/donations">donations</a> · <a href="https://github.com/opesoid" target="_blank" rel="noopener noreferrer" aria-label="GitHub profile (opens in new tab)">github</a></p> 132 </footer> 133 134</div>
vendor: 110 bytes, lines 134-136
134 135 136<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>
136<script src="/assets/js/main.js?v=1787580896" defer></script>
vendor: 1 bytes, line 136
136
137<script>(function(){function c(){var b=a.contentDocument||(a.contentWindow&&a.contentWindow.document);if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'a440116de937514c',t:'MTc5MDkwNTk1MA=='};var a=document.createElement('script');a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script>
137</body> 138</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.