PageSourceSearch

https://iter.co/en/apply

html iter.co collected 2026-10-09 23:19:50 UTC 30,189 bytes, 307 lines download raw bytes

1<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><meta name="generator" content="Astro v7.2.10"><meta name="description" content="Apply to partner with iterco."><link rel="canonical" href="https://iter.co/en/apply"><link rel="alternate" hreflang="en" href="https://iter.co/en/apply"><link rel="alternate" hreflang="zh-CN" href="https://iter.co/zh-cn/apply"><link rel="alternate" hreflang="zh-Hant-TW" href="https://iter.co/zh-hktw/apply"><link rel="alternate" hreflang="id" href="https://iter.co/id/apply"><link rel="alternate" hreflang="x-default" href="https://iter.co/en/apply"><meta property="og:type" content="website"><meta property="og:title" content="Apply | iterco"><meta property="og:description" content="Apply to partner with iterco."><meta property="og:url" content="https://iter.co/en/apply"><meta property="og:image" content="https://iter.co/images/meta_image.png"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:title" content="Apply | iterco"><meta name="twitter:description" content="Apply to partner with iterco."><meta name="twitter:image" content="https://iter.co/images/meta_image.png">
1<script type="application/ld+json">{"@context":"https://schema.org","@type":"Organization","name":"iterco","url":"https://iter.co/","logo":"https://iter.co/images/favicon.png"}</script>
1<link href="/css/normalize.css" rel="stylesheet" type="text/css"><link href="/css/webflow.css" rel="stylesheet" type="text/css"><link href="/css/iterco.webflow.css" rel="stylesheet" type="text/css">
1<script type="text/javascript">
2            !(function (o, c) {
3                var n = c.documentElement,
4                    t = " w-mod-";
5                ((n.className += t + "js"),
6                    ("ontouchstart" in o ||
7                        (o.DocumentTouch && c instanceof DocumentTouch)) &&
8                        (n.className += t + "touch"));
9            })(window, document);
10        </script>
10<link rel="icon" type="image/png" href="/images/favicon.png"><link rel="apple-touch-icon" href="/images/webclip.png"><title>Apply | iterco</title><style>.muted{color:#5f6576}.inline-link{color:inherit;text-underline-offset:2px;text-decoration:underline}.reveal{opacity:0;animation:.7s forwards reveal-up;transform:translateY(16px)}.reveal-stagger>*{opacity:0;animation:.65s forwards reveal-up;transform:translateY(14px)}.reveal-stagger>:nth-child(2){animation-delay:80ms}.reveal-stagger>:nth-child(3){animation-delay:.16s}.reveal-stagger>:nth-child(4){animation-delay:.24s}.scroll-reveal{opacity:0;transition:opacity .7s,transform .7s;transform:translateY(28px)}.scroll-reveal.is-visible{opacity:1;transform:translateY(0)}@keyframes reveal-up{to{opacity:1;transform:translateY(0)}}a:focus-visible,button:focus-visible,input:focus-visible,textarea:focus-visible{outline-offset:2px;outline:2px solid #0054d1}.form-input:focus-visible{outline:none}.field-wrapper.span-2{grid-column:span 2/span 2}.field-error{color:#c0392b;pointer-events:none;margin-top:6px;font-family:Nowalt,Arial,sans-serif;font-size:14px;line-height:1.2;position:absolute;top:100%;left:0;right:0}.form-input.has-error{border-bottom-color:#c0392b}.consent-banner{border:1px solid var(--border);z-index:40;background:#fff;border-radius:8px;gap:12px;width:min(620px,100% - 32px);padding:16px;font-size:14px;line-height:1.45;display:grid;position:fixed;bottom:16px;left:16px;box-shadow:0 10px 30px #020c1b1f}.consent-banner[hidden]{display:none}.consent-banner p{margin:0}.consent-actions{gap:8px;display:flex}.consent-actions button{color:#fff;cursor:pointer;background:#0054d1;border:1px solid #004bb7;border-radius:6px;padding:7px 12px;font-family:inherit;font-size:14px;line-height:1.25}.consent-actions .secondary{color:#1f2937;background:#fff;border-color:#c7cedd}.language-toggle{justify-content:center;min-width:48px;padding-right:28px}.language-toggle-icon{justify-content:center;align-items:center;display:inline-flex}.logos-component .div-block-24{grid-column:1/-1}.address-link-secondary{margin-top:.5rem}.not-found-section{min-height:55vh}.not-found-content{flex-direction:column;align-items:flex-start;gap:1.5rem;max-width:48rem;display:flex}.not-found-content p{margin:0}.game-gallery-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.game-gallery-grid>img{aspect-ratio:16/9;object-fit:cover;width:100%}@media (width<=991px){.div-block-3.w-nav-menu{padding-left:0;padding-right:0}.div-block-3.w-nav-menu .w-nav-link,.div-block-3.w-nav-menu .sublink{justify-content:space-between;align-items:center;width:100%;padding:16px 20px;display:flex}.div-block-3.w-nav-menu .w-dropdown{width:100%;display:block}.div-block-3.w-nav-menu .dropdown-list-9-2{padding-top:0}.div-block-3.w-nav-menu .w-dropdown-link{padding-left:20px;padding-right:20px}.language-toggle{justify-content:space-between;min-width:0;padding-right:20px}.language-toggle .down-arrow-9{margin-right:0}}@media (width<=760px){.consent-actions{grid-template-columns:1fr 1fr;display:grid}.game-gallery-grid{grid-template-columns:1fr}}@media (prefers-reduced-motion:reduce){.reveal,.reveal-stagger>*{opacity:1;animation:none;transform:none}.scroll-reveal{opacity:1;transition:none;transform:none}}
11</style></head><body class="body"><div data-animation="default" data-collapse="medium" data-duration="400" data-easing="ease" data-easing2="ease" role="banner" class="navbar w-nav"><div class="div-block page-padding"><div class="container containder-large"><div class="navbar-inside"><a href="/en" class="link-block w-nav-brand"><img width="150" loading="eager" alt="site logo" src="/images/Iterco-Primary-Blue.svg"></a><nav class="div-block-3 w-nav-menu"><a href="/en/games" class="link-2 w-nav-link">Games</a><a href="/en/about" class="link-2 w-nav-link">About</a><a href="/en/apply" class="link-2 w-nav-link w--current">Apply</a><div data-delay="0" data-hover="true" class="dropdown-9 w-dropdown"><div class="sublink language-toggle w-dropdown-toggle" aria-label="Language" title="Language"><div class="language-toggle-icon" aria-hidden="true"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="12" cy="12" r="9" stroke="currentColor" stroke-width="1.8"></circle><path d="M3.5 12H20.5" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"></path><path d="M12 3C14.9 5.8 16.5 8.8 16.5 12C16.5 15.2 14.9 18.2 12 21" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"></path><path d="M12 3C9.1 5.8 7.5 8.8 7.5 12C7.5 15.2 9.1 18.2 12 21" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"></path></svg></div><div class="down-arrow-9 w-icon-dropdown-toggle"></div></div><nav class="dropdown-list-9-2 w-dropdown-list"><a href="/en/apply" class="link-2 w-dropdown-link w--current">English</a><a href="/zh-cn/apply" class="link-2 w-dropdown-link">简体中文</a><a href="/zh-hktw/apply" class="link-2 w-dropdown-link">繁體中文</a><a href="/id/apply" class="link-2 w-dropdown-link">Bahasa Indonesia</a></nav></div></nav><div class="menu-button-9 w-nav-button"><div class="hamburger-9 w-icon-nav-menu"></div></div></div></div></div></div><main><div><section><div class="div-block page-padding"><div class="container containder-large"><div class="padding-huge padding-vertical"><div class="apply-component reveal-stagger"><div class="terms-wrapper"><div class="text-size-medium">We aim for fair contracts that ensure that developers get revenue from their game from day 1.</div><div class="terms-number-wrapper"><div class="terms-numbers"><div class="div-block-29"><div class="text-block-9"><span class="text-span-5">Before<br></span>1x ROI</div></div><div class="rev-share"><div class="div-block-31"><div class="text-block-10">For Developers:</div><div class="text-size-large">20%</div></div></div><div class="rev-share"><div class="div-block-31"><div class="text-block-42">For iterco:</div><div class="text-size-large">80%</div></div></div></div><div class="terms-numbers"><div class="div-block-29"><div class="text-block-9"><span class="text-span-5">After<br></span>1x ROI</div></div><div class="rev-share"><div class="div-block-31"><div class="text-block-10">For Developers:</div><div class="text-size-large">60%</div></div></div><div class="rev-share"><div class="div-block-31"><div class="text-block-35">For iterco:</div><div class="text-size-large">40%</div></div></div></div></div></div></div><div class="text-block-12 reveal">1x ROI is calculated as the sum of cost incurred in the publishing of the game</div></div></div></div></section><section><div class="div-block page-padding"><div class="container containder-large"><div class="padding-huge padding-vertical"><div class="apply-about-component reveal-stagger"><div class="apply-about-image-text-wrap-copy"><div class="tag-text">//2024</div><div class="div-block-18"><img src="/images/IkoneIIsland---SS1.jpg" loading="lazy" alt="Ikonei Island" class="image-4"></div></div><div class="home-about-text-wrap"><div class="margin-medium margin-bottom"><div class="text-size-large">We are looking for a perfect blend of style and substance, igniting a sense of adventure that you and your friends won&#39;
11t want to miss.</div></div><div class="margin-medium margin-bottom"><div class="text-block-11">What we love:</div><ul><li class="list-item-5"><strong>Cozy</strong>: Warm, inviting visuals that create a comforting and immersive atmosphere, drawing players in with charm and appeal.</li><li class="list-item-6"><strong>Substance</strong>: Deep gameplay mechanics, offering players meaningful choices and challenges.</li><li class="list-item-7"><strong>Adventure</strong>: Immersive worlds teeming with exploration, discovery, and excitement.</li><li class="list-item-8"><strong>Fun with Friends</strong>: Engaging and dynamic multiplayer experiences, creating unforgettable moments amongst friends.</li><li class="list-item-9"><strong>Southeast Asian Devs</strong>: Embracing regional talent, culture and innovation.</li></ul></div></div></div></div></div></div></section><section><div class="div-block page-padding"><div class="container containder-large"><div class="padding-huge padding-vertical"><div class="apply-component"><h1 class="heading-large reveal">Apply now</h1><div class="div-block-32 reveal-stagger"><div class="form-block w-form"><form id="apply-form" method="post" action="/api/forms/apply" class="form" novalidate data-recaptcha-site-key><div class="div-block-34"><div class="field-wrapper"><label for="fullName" class="field_label-2 large">Full name</label><input class="form-input w-input" maxlength="256" name="fullName" type="text" id="fullName" required><div class="black-line-animation"></div></div><div class="field-wrapper"><label for="email" class="field_label-2 large">Email</label><input class="form-input w-input" maxlength="256" name="email" type="email" id="email" required><div class="black-line-animation"></div></div><div class="field-wrapper"><label for="studioName" class="field_label-2 large">Studio Name</label><input class="form-input w-input" maxlength="256" name="studioName" type="text" id="studioName"><div class="black-line-animation"></div></div><div class="field-wrapper"><label for="studioLocation" class="field_label-2 large">Studio Location</label><input class="form-input w-input" maxlength="256" name="studioLocation" type="text" id="studioLocation"><div class="black-line-animation"></div></div><div class="field-wrapper"><label for="gameName" class="field_label-2 large">Game Name</label><input class="form-input w-input" maxlength="256" name="gameName" type="text" id="gameName" required><div class="black-line-animation"></div></div><div class="field-wrapper"><label for="pitchDeckLink" class="field_label-2 large">Link to Game Pitch Deck</label><input class="form-input w-input" maxlength="2048" name="pitchDeckLink" type="text" inputmode="url" autocapitalize="none" spellcheck="false" id="pitchDeckLink" required><div class="black-line-animation"></div></div><div class="field-wrapper span-2"><label for="gamePitch" class="field_label-2 large">Elevator Pitch</label><textarea id="gamePitch" name="gamePitch" maxlength="5000" class="form-input w-input"></textarea><div class="black-line-animation"></div></div><div class="field-wrapper span-2"><label for="graphicsStyle" class="field_label-2 large">What makes the graphical style stand out?</label><textarea id="graphicsStyle" name="graphicsStyle" maxlength="5000" class="form-input w-input"></textarea><div class="black-line-animation"></div></div><div class="field-wrapper span-2"><label for="gameplayDepth" class="field_label-2 large">What makes the game deep?</label><textarea id="gameplayDepth" name="gameplayDepth" maxlength="5000" class="form-input w-input"></textarea><div class="black-line-animation"></div></div><div class="field-wrapper span-2"><label for="adventure" class="field_label-2 large">How does the game evoke a sense of adventure?</label><textarea id="adventure" name="adventure" maxlength="5000" class="form-input w-input"></textarea><div class="black-line-animation"></div></div><div class="field-wrapper"><label for="demoLink" class="field_label-2 large">Link to Demo</label><input class="form-input w-input" maxlength="2048" name="demoLink" type="text" inputmode="url" autocapitalize="none" spellcheck="false" id="demoLink"><div class="black-line-animation"></div></div><div class="field-wrapper"><label for="gameplayVideoLink" class="field_label-2 large">Link to Gameplay Video</label><input class="form-input w-input" maxlength="2048" name="gameplayVideoLink" type="text" inputmode="url" autocapitalize="none" spellcheck="false" id="gameplayVideoLink"><div class="black-line-animation"></div></div><div class="field-wrapper span-2"><label class="hire-fild-label bottom-16">
11Is there any multiplayer?</label><div class="checkboxes maxwidth-470"><label class="w-checkbox hire-checkbox"><div class="w-checkbox-input w-checkbox-input--inputType-custom checkbox-2"></div><input type="checkbox" name="multiplayer" value="pvp" style="opacity:0;position:absolute;z-index:-1"><span class="checkbox-label-2 is--clickable-off w-form-label">PvP</span></label><label class="w-checkbox hire-checkbox"><div class="w-checkbox-input w-checkbox-input--inputType-custom checkbox-2"></div><input type="checkbox" name="multiplayer" value="co-op" style="opacity:0;position:absolute;z-index:-1"><span class="checkbox-label-2 is--clickable-off w-form-label">Co-op</span></label><label class="w-checkbox hire-checkbox"><div class="w-checkbox-input w-checkbox-input--inputType-custom checkbox-2"></div><input type="checkbox" name="multiplayer" value="singleplayer-only" style="opacity:0;position:absolute;z-index:-1"><span class="checkbox-label-2 is--clickable-off w-form-label">Singleplayer Only</span></label></div></div></div><input type="hidden" name="recaptchaToken" value=""><input type="submit" class="button w-button" value="Submit Application"><p id="apply-form-status" class="muted" aria-live="polite"></p></form></div></div></div></div></div></div></section></div></main><section class="footer"><div class="div-block page-padding"><div class="container containder-large"><div class="padding-huge padding-top"><div class="footer-inside"><div class="footer-top"><div class="max-width-medium"><div class="margin-medium margin-bottom"><div class="text-size-large">Let&#39;s craft something extraordinary, together.</div></div><a href="/en/contact" class="new-button margin-bottom-24px w-inline-block"><div class="buttontext">Contact</div><div class="button-arrow-wrap"><img loading="lazy" src="/images/65b30b1736d30f0087eeca1d_Arrow-7.svg" alt="" class="button-arrow-absolute"><img loading="lazy" src="/images/65b30b1736d30f0087eeca1d_Arrow-7.svg" alt="" class="button-arrow"></div></a><div class="footer-social-links"><a href="https://x.com/iterco_games" target="_blank" rel="noreferrer" class="footer-social-link footer-social-link--x" aria-label="X" title="X"><svg class="footer-social-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817-5.966 6.817H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231 5.45-6.231Zm-1.161 17.52h1.833L7.084 4.126H5.117L17.083 19.77Z" fill="currentColor"></path></svg></a><a href="https://www.linkedin.com/company/iterco" target="_blank" rel="noreferrer" class="footer-social-link footer-social-link--linkedin" aria-label="LinkedIn" title="LinkedIn"><svg class="footer-social-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M5.2 3.5a2.2 2.2 0 1 1 0 4.4 2.2 2.2 0 0 1 0-4.4ZM3.4 9h3.6v11.5H3.4V9Zm5.8 0h3.4v1.6h.05c.47-.9 1.63-1.95 3.36-1.95 3.6 0 4.25 2.37 4.25 5.45v6.4h-3.6v-5.67c0-1.35-.03-3.09-1.88-3.09-1.88 0-2.17 1.47-2.17 2.99v5.77H9.2V9Z" fill="currentColor"></path></svg></a><a href="https://www.instagram.com/iterco_games" target="_blank" rel="noreferrer" class="footer-social-link footer-social-link--instagram" aria-label="Instagram" title="Instagram"><svg class="footer-social-icon" viewBox="0 0 24 24" aria-hidden="true"><rect x="3.25" y="3.25" width="17.5" height="17.5" rx="4.5" fill="none" stroke="currentColor" stroke-width="1.8"></rect><circle cx="12" cy="12" r="4.1" fill="none" stroke="currentColor" stroke-width="1.8"></circle><circle cx="17.35" cy="6.7" r="1.05" fill="currentColor"></circle></svg></a></div></div><div class="footer-col"><div class="tag-text">About</div><a href="/en/about" class="link-3">About</a><a href="/en/apply" class="link-3 w--current">Apply</a><a href="/en/contact" class="link-3">Contact</a><a href="/en/privacypolicy" class="link-3">Privacy Policy</a></div><div class="footer-col footer-col--games"><div class="tag-text">Games</div><a href="/en/games/moonfrost" class="link-3">Moonfrost</a><a href="/en/games/o2gether" class="link-3">O2GETHER</a><a href="/en/games/aila" class="link-3">A.I.L.A</a><a href="/en/games/wild-country" class="link-3">Wild Country</a><a href="/en/games/ikonei-island" class="link-3">Ikonei Island</a><a href="/en/games/scarred" class="link-3">Scarred</a><a href="/en/games/homeseek" class="link-3">Homeseek</a><a href="/en/games/sigil-of-the-magi" class="link-3">Sigil of the Magi</a><a href="/en/games/knight-crawlers" class="link-3">Knight Crawlers</a><a href="/en/games/the-signal-state" class="link-3">The Signal State</a></div><div class="footer-col"><div class="tag-text">Studios</div><a href="https://kopiforge.com" target="_blank" class="link-3">kopiforge</a><a href="https://iterhaus.com" target="_blank" class="link-3">iterhaus</a></div></div></div></div></div></div></section><div id="consent-banner" class="consent-banner" hidden><p>We use analytics cookies to improve site quality. You can accept or decline analytics tracking. Read our <a href="/en/privacypolicy">Privacy Policy</a>.</p><div class="consent-actions"><button type="button" id="consent-accept">Accept</button><button type="button" id="consent-decline" class="secondary">Decline</button></div></div>
11<script>(function(){const gaId = "";
12const requiresConsent = false;
13
14    const KEY = "iterco.analytics.consent";
15    const banner = document.getElementById("consent-banner");
16    const accept = document.getElementById("consent-accept");
17    const decline = document.getElementById("consent-decline");
18
19    function loadAnalytics() {
20        if (!gaId) return;
21        if (document.getElementById("ga-script")) return;
22
23        const s = document.createElement("script");
24        s.id = "ga-script";
25        s.async = true;
26        s.src = `https://www.googletagmanager.com/gtag/js?id=${gaId}`;
27        document.head.appendChild(s);
28
29        window.dataLayer = window.dataLayer || [];
30        window.gtag = function gtag() {
31            window.dataLayer.push(arguments);
32        };
33
34        window.gtag("js", new Date());
35        window.gtag("config", gaId);
36    }
37
38    function setConsent(value) {
39        localStorage.setItem(KEY, value);
40        if (value === "accepted") {
41            loadAnalytics();
42        }
43        banner?.setAttribute("hidden", "hidden");
44    }
45
46    if (gaId) {
47        const existing = localStorage.getItem(KEY);
48        if (!requiresConsent || existing === "accepted") {
49            loadAnalytics();
50        } else if (existing === "declined") {
51            banner?.setAttribute("hidden", "hidden");
52        } else {
53            banner?.removeAttribute("hidden");
54        }
55
56        accept?.addEventListener("click", () => setConsent("accepted"));
57        decline?.addEventListener("click", () => setConsent("declined"));
58    }
59})();</script>
59<script src="https://d3e54v103j8qbb.cloudfront.net/js/jquery-3.5.1.min.dc5e7f18c8.js" type="text/javascript" defer></script>
59<script src="/js/webflow.js" type="text/javascript" defer></script>
59<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v4bc70e2c01a94c73b74392e4234840661791215815920" integrity="sha512-L0ha0OXavK/8okipN9F8BtP84dg9DUhPERbBXzwI6dgTA55d2+yweo3pn5CSFYs45/r8md2+xvUPtTdvTNRfjA==" data-cf-beacon='{"version":"2024.11.0","token":"6ece4bf080af4ae29c6cd01ea6a44388","r":1,"spa":2}' crossorigin="anonymous"></script>
59
60</body></html>
60<script>(function(){const fieldLabels = {"fullName":"Full name","email":"Email","studioName":"Studio Name","studioLocation":"Studio Location","gameName":"Game Name","pitchDeckLink":"Link to Game Pitch Deck","gamePitch":"Elevator Pitch","graphicsStyle":"What makes the graphical style stand out?","gameplayDepth":"What makes the game deep?","adventure":"How does the game evoke a sense of adventure?","demoLink":"Link to Demo","gameplayVideoLink":"Link to Gameplay Video"};
61const formMessages = {"requiredSuffix":"is required.","invalidEmail":"Enter a valid email address.","invalidUrl":"Enter a valid link, for example example.com/deck","multiplayerRequired":"Select at least one multiplayer option.","submitting":"Submitting...","fixFields":"Please fix the highlighted fields.","success":"Application sent successfully.","failed":"Submission failed."};
62
63    const form = document.querySelector("#apply-form");
64    const statusEl = document.querySelector("#apply-form-status");
65
66    const URL_FIELDS = ["pitchDeckLink", "demoLink", "gameplayVideoLink"];
67    const REQUIRED_FIELDS = ["fullName", "email", "gameName", "pitchDeckLink"];
68    const FIELD_LABELS = fieldLabels;
69
70    function withProtocol(value) {
71        if (!value) return value;
72        return /^[a-z][a-z0-9+.-]*:\/\//i.test(value)
73            ? value
74            : `https://${value}`;
75    }
76
77    function isHttpUrl(value) {
78        try {
79            const url = new URL(withProtocol(value));
80            return (
81                (url.protocol === "http:" || url.protocol === "https:") &&
82                url.hostname.includes(".")
83            );
84        } catch {
85            return false;
86        }
87    }
88
89    function fieldError(input) {
90        const name = input.name;
91        const value = input.value.trim();
92
93        if (REQUIRED_FIELDS.includes(name) && !value) {
94            return `${FIELD_LABELS[name]} ${formMessages.requiredSuffix}`;
95        }
96        if (!value) return "";
97        if (name === "email" && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
98            return formMessages.invalidEmail;
99        }
100        if (URL_FIELDS.includes(name) && !isHttpUrl(value)) {
101            return formMessages.invalidUrl;
102        }
103        return "";
104    }
105
106    function setError(wrapper, message) {
107        if (!wrapper) return;
108        let el = wrapper.querySelector(".field-error");
109
110        if (!message) {
111            el?.remove();
112            return;
113        }
114
115        if (!el) {
116            el = document.createElement("span");
117            el.className = "field-error";
118            el.setAttribute("aria-live", "polite");
119            wrapper.appendChild(el);
120        }
121        el.textContent = message;
122    }
123
124    function validateField(input) {
125        const message = fieldError(input);
126        setError(input.closest(".field-wrapper"), message);
127        input.classList.toggle("has-error", Boolean(message));
128        if (message) {
129            input.setAttribute("aria-invalid", "true");
130        } else {
131            input.removeAttribute("aria-invalid");
132        }
133        return !message;
134    }
135
136    function validateMultiplayer(currentForm) {
137        const ok =
138            currentForm.querySelectorAll('input[name="multiplayer"]:checked')
139                .length > 0;
140        const wrapper = currentForm
141            .querySelector(".checkboxes")
142            ?.closest(".field-wrapper");
143        setError(wrapper, ok ? "" : formMessages.multiplayerRequired);
144        return ok;
145    }
146
147    function validateForm(currentForm) {
148        let firstInvalid = null;
149
150        for (const input of currentForm.querySelectorAll(".form-input")) {
151            if (!(
152                input instanceof HTMLInputElement ||
153                input instanceof HTMLTextAreaElement
154            ))
155                continue;
156            if (!validateField(input) && !firstInvalid) firstInvalid = input;
157        }
158
159        const multiplayerOk = validateMultiplayer(currentForm);
160        firstInvalid?.focus();
161        return firstInvalid === null && multiplayerOk;
162    }
163
164    function normalizeUrlFields(currentForm) {
165        for (const fieldName of URL_FIELDS) {
166            const input = currentForm.querySelector(
167                `input[name="${fieldName}"]`,
168            );
169            if (!(input instanceof HTMLInputElement)) continue;
170
171            const value = input.value.trim();
172            if (!value) continue;
173
174            input.value = withProtocol(value);
175        }
176    }
177
178    function bindFieldAnimations() {
179        const inputs = document.querySelectorAll(".form-input");
180
181        for (const input of inputs) {
182            input.addEventListener("focusin", () => {
183                const wrapper = input.parentElement;
184                const label = wrapper?.querySelector(".field_label-2");
185                const line = wrapper?.querySelector(".black-line-animation");
186                label?.classList.remove("large");
187                line?.classList.add("full");
188            });
189
190            input.addEventListener("focusout", () => {
191                const wrapper = input.parentElement;
192                const label = wrapper?.querySelector(".field_label-2");
193                const line = wrapper?.querySelector(".black-line-animation");
194                if (!(
195                    input instanceof HTMLInputElement ||
196                    input instanceof HTMLTextAreaElement
197                ))
198                    return;
199                if (input.value.length === 0) {
200                    label?.classList.add("large");
201                    line?.classList.remove("full");
202                }
203                if (
204                    input.name in FIELD_LABELS ||
205                    REQUIRED_FIELDS.includes(input.name)
206                ) {
207                    if (
208                        URL_FIELDS.includes(input.name) &&
209                        isHttpUrl(input.value.trim())
210                    ) {
211                        input.value = withProtocol(input.value.trim());
212                    }
213                    validateField(input);
214                }
215            });
216
217            // once a field has been flagged, re-check as they type so the error clears itself
218            input.addEventListener("input", () => {
219                if (input.classList.contains("has-error")) validateField(input);
220            });
221        }
222
223        const checks = document.querySelectorAll(".checkbox-2");
224        for (const box of checks) {
225            box.addEventListener("click", () => {
226                box.parentElement
227                    ?.querySelector(".checkbox-label-2")
228                    ?.classList.toggle("is--active");
229            });
230        }
231
232        for (const box of document.querySelectorAll(
233            'input[name="multiplayer"]',
234        )) {
235            box.addEventListener("change", () => {
236                if (form) validateMultiplayer(form);
237            });
238        }
239    }
240
241    async function ensureRecaptchaToken() {
242        if (!form) return;
243
244        const siteKey = form.getAttribute("data-recaptcha-site-key");
245        if (!siteKey) return;
246
247        if (!window.grecaptcha) {
248            await new Promise((resolve, reject) => {
249                const script = document.createElement("script");
250                script.src = `https://www.google.com/recaptcha/api.js?render=${siteKey}`;
251                script.async = true;
252                script.defer = true;
253                script.onload = resolve;
254                script.onerror = reject;
255                document.head.appendChild(script);
256            });
257        }
258
259        await new Promise((resolve) => window.grecaptcha.ready(resolve));
260        const token = await window.grecaptcha.execute(siteKey, {
261            action: "apply_form_submit",
262        });
263        const tokenInput = form.querySelector('input[name="recaptchaToken"]');
264
265        if (tokenInput) {
266            tokenInput.value = token;
267        }
268    }
269
270    bindFieldAnimations();
271
272    form?.addEventListener("submit", async (event) => {
273        event.preventDefault();
274        if (!statusEl || !form) return;
275
276        statusEl.textContent = formMessages.submitting;
277
278        try {
279            if (!validateForm(form)) {
280                statusEl.textContent = formMessages.fixFields;
281                return;
282            }
283
284            normalizeUrlFields(form);
285            await ensureRecaptchaToken();
286
287            const response = await fetch(form.action, {
288                method: "POST",
289                body: new FormData(form),
290            });
291
292            const result = await response.json();
293            if (response.ok && result.ok) {
294                statusEl.textContent = formMessages.success;
295                form.reset();
296                for (const el of form.querySelectorAll(".field-error"))
297                    el.remove();
298                for (const el of form.querySelectorAll(".has-error"))
299                    el.classList.remove("has-error");
300            } else {
301                statusEl.textContent = result.error || formMessages.failed;
302            }
303        } catch {
304            statusEl.textContent = formMessages.failed;
305        }
306    });
307})();</script>

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.