1<!DOCTYPE html> 2<html lang="ko"> 3<head> 4<meta charset="utf-8" /> 5<meta name="viewport" content="width=device-width, initial-scale=1" /> 6<title>Neona · ëì 문ì</title> 7<meta name="robots" content="noindex" /> 8<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> 9<link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin /> 10<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/[email protected]/dist/web/variable/pretendardvariable-dynamic-subset.min.css" /> 11<style> 12 * { margin: 0; padding: 0; box-sizing: border-box; } 13 body { font-family: "Pretendard Variable", Pretendard, -apple-system, sans-serif; background: #fafafb; color: #0b0b0c; } 14 .topbar { background: #050506; padding: 14px 24px; } 15 .topbar a { color: #b7b7bd; text-decoration: none; font-size: 15px; font-weight: 600; } 16 .wrap { max-width: 560px; margin: 48px auto 80px; padding: 0 20px; } 17 h1 { font-size: 28px; letter-spacing: -0.02em; margin-bottom: 10px; } 18 .desc { color: #6f6f78; font-size: 15px; line-height: 1.6; margin-bottom: 32px; } 19 .card { background: #fff; border: 1px solid #eeeef1; border-radius: 16px; padding: 28px; } 20 label { display: block; font-size: 13.5px; font-weight: 600; margin: 18px 0 6px; } 21 label:first-child { margin-top: 0; } 22 label .req { color: #16a34a; } 23 input, textarea, select { width: 100%; font: inherit; font-size: 15px; padding: 11px 14px; border: 1px solid #d9d9df; border-radius: 10px; background: #fff; color: inherit; } 24 input:focus, textarea:focus, select:focus { outline: none; border-color: #16a34a; } 25 textarea { min-height: 120px; resize: vertical; } 26 .privacy { display: flex; align-items: flex-start; gap: 8px; margin: 20px 0 0; font-size: 13.5px; color: #4a4a52; } 27 .privacy input { width: auto; margin-top: 2px; } 28 .privacy a { color: #16a34a; } 29 button { width: 100%; margin-top: 24px; font: inherit; font-size: 15.5px; font-weight: 700; color: #fff; background: #16a34a; border: 0; border-radius: 999px; padding: 13px; cursor: pointer; } 30 button:disabled { opacity: 0.55; cursor: default; } 31 .msg { margin-top: 16px; font-size: 14px; display: none; } 32 .msg.error { color: #dc2626; display: block; } 33 .success { text-align: center; padding: 40px 12px; display: none; } 34 .success h2 { font-size: 22px; margin-bottom: 10px; } 35 .success p { color: #6f6f78; font-size: 15px; line-height: 1.6; } 36</style> 37</head> 38<body> 39<div class="topbar"><a href="/">â Neona íì¼ë¡</a></div> 40<div class="wrap"> 41 <h1>ëì 문ì</h1> 42 <p class="desc">
42ë¤ì¤ë ìì´ì í¸ ëì ·ë°ëª¨ ìì²ì ë¨ê²¨ì£¼ì¸ì. ìì ì¼ ê¸°ì¤ 1~2ì¼ ë´ì íì ë립ëë¤.</p> 43 <!-- ë°ëª¨ ìì²(intent=demo_request)ì¼ë¡ ë¤ì´ì¨ ê²½ì° â ë른 ì¹´ëê° ìë íìëë¤ (CTA-LINKS §4.5) --> 44 <div id="demoBadge" style="display:none; margin:-16px 0 24px; padding:12px 16px; background:#f4fbf7; border:1px solid #d3ecd9; border-radius:12px; font-size:14px; color:#0f5132;"> 45 ìì² ë°ëª¨: <strong data-demo-title></strong> 46 </div> 47 <div class="card"> 48 <form id="inquiryForm" novalidate> 49 <label for="f-name">ì´ë¦ <span class="req">*</span></label> 50 <input id="f-name" name="name" required maxlength="150" autocomplete="name" /> 51 <label for="f-email">íì¬ ì´ë©ì¼ <span class="req">*</span></label> 52 <input id="f-email" name="email" type="email" required maxlength="254" autocomplete="email" /> 53 <label for="f-company">íì¬ëª <span class="req">*</span></label> 54 <input id="f-company" name="company" required maxlength="200" autocomplete="organization" /> 55 <label for="f-phone">ì°ë½ì² <span class="req">*</span></label> 56 <input id="f-phone" name="phone" required maxlength="13" inputmode="numeric" autocomplete="tel" placeholder="010-0000-0000" /> 57 <!-- salesmap 리ëì `문ì ì í(ë¤ì¤ëìì´ì í¸)`. ìµì í ì¤í¸ê° 그쪽 ì íì§ì 58 문ì ê·¸ëë¡ ê°ìì¼ ê°ì´ ì¤ë¦°ë¤ â src/lib/api/inquiries.ts ì INQUIRY_TYPES ì ëì¼. --> 59 <label for="f-inquiry-type">ì´ë¤ ê²ì´ íìíì ê°ì?</label> 60 <select id="f-inquiry-type" name="inquiry_type"> 61 <option value="">ì íí´ ì£¼ì¸ì (ì í)</option> 62 <option>ê³ ê° ìë´Â·ë¬¸ì ìë</option> 63 <option>ììë°ì´ë ìì ì½</option> 64 <option>AI íí°Â·íìµ ëí</option> 65 <option>ìì± ìºë¦í°Â·IP íì¬</option> 66 <option>기í / ìì§ ë¯¸ì </option> 67 </select> 68 <label for="f-message">문ì ë´ì©</label> 69 <textarea id="f-message" name="message" maxlength="2000" placeholder="ëì íë ¤ë ìë리ì¤, ìì ê·ëª¨, ê¶ê¸í ì ì ìë ¤ì£¼ì¸ì."></textarea> 70 <label class="privacy"><input id="f-privacy" type="checkbox" required /> 71 <span><a href="/privacy" target="_blank" rel="noopener">ê°ì¸ì ë³´ ì²ë¦¬ë°©ì¹¨</a>ì ë°ë¼ 문ì ìë 목ì ì¼ë¡ ê°ì¸ì 보를 ìì§Â·ì´ì©íë ë° ëìí©ëë¤. <span class="req">*</span></span> 72 </label> 73 <button id="submitBtn" type="submit">문ì ë³´ë´ê¸°</button> 74 <p class="msg" id="formMsg"></p> 75 </form> 76 <div class="success" id="successPanel"> 77 <h2>문ìê° ì ìëììµëë¤</h2> 78 <p>ë¨ê²¨ì£¼ì ì´ë©ì¼ë¡ ê³§ ì°ë½ëë¦¬ê² ìµëë¤.<br /><a href="/" style="color:#16a34a;">íì¼ë¡ ëìê°ê¸°</a></p> 79 </div> 80 </div> 81</div>
82<script src="/env-config.js"></script>
vendor: 1 bytes, line 82
82
83<script src="/assets/attribution.js"></script>
vendor: 1 bytes, line 83
83
84<script defer src="/assets/analytics.js"></script>
vendor: 1 bytes, line 84
84
85<script> 86(function () { 87 "use strict"; 88 var API_ROOT = ((window.ENV && window.ENV.VITE_API_URL) || "http://localhost:8000/api").replace(/\/api\/?$/, ""); 89 var form = document.getElementById("inquiryForm"); 90 91 /* ââ CTA íë¼ë¯¸í° ìì (CTA-LINKS.md §4.2) âââââââââââââââââââââââââââââ 92 * ëë©ì cta.js ê° ì´ë ë²í¼ìì ìëì§ë¥¼ ì¿¼ë¦¬ë¡ ë긴ë¤. ìë¡ê³ 침íë©´ ì¿¼ë¦¬ê° 93 * ì¬ë¼ì§ë¯ë¡ 첫 ì§ì ì sessionStorage ë¡ í ë² ë³´ê´íë¤. intent ê° ë¦¬ë ì±ê²© 94 * (contact | self_serve | demo_request)ì ê°ë¥¸ë¤ â ì¸ì¼ì¦ë§µê¹ì§ ê·¸ëë¡ ê°ë¤. */ 95 /* í¤: ë°±ìë ì¤í¤ë§ì max_length. ë겨 ë³´ë´ë©´ 422 ë¡ í¼ ì ì²´ê° ì£½ì¼ë¯ë¡ ì¬ê¸°ì ë§ì¶° ìë¥¸ë¤ 96 * (ì ì íë¦ìì ì ëì§ë§, ë³ì¡°Â·ì´ì URL ì´ ì ì¶ ì¤í¨ë¡ ì´ì´ì§ë©´ ì ëë¤) */ 97 var CTA_KEYS = { intent: 20, cta_id: 50, cta_position: 30, cta_text: 100, demo_id: 100, demo_name: 100, page_path: 100 }; 98 // ì´ì ë¹ëì persistent PII handoffë ë ì´ì ì¬ì©íì§ ìê³ ì´ë¤ íì´ì§ììë ë°ê²¬ ì¦ì í기íë¤. 99 try { 100 Object.keys(localStorage).forEach(function (key) { 101 if (key.indexOf("neona_demo_form:") === 0 || key === "neona_demo_form") localStorage.removeItem(key); 102 }); 103 } catch (e) {} 104 var demoToken = ""; 105 var cta = (function () { 106 var saved = null; 107 try { saved = JSON.parse(sessionStorage.getItem("neona_cta") || "null"); } catch (e) {} 108 var q = new URLSearchParams(location.search), out = {}, has = false; 109 // URLìë íì© í¤ cta_idì ë¹ìë³ tokenë§ ëë¤. PIIë source tab ë©ëª¨ë¦¬ìì 110 // BroadcastChannel ìëµì¼ë¡ í ë²ë§ ì ë¬ëë©° persistent storageì 기ë¡íì§ ìëë¤. 111 var tokenMatch = (q.get("cta_id") || "").match(/^demo_request\.([a-z0-9]{8,32})$/); 112 if (tokenMatch) demoToken = tokenMatch[1]; 113 Object.keys(CTA_KEYS).forEach(function (k) { 114 var v = q.get(k); 115 if (!v) return; 116 if (k === "cta_id" && tokenMatch) v = "demo_request"; 117 out[k] = v.slice(0, CTA_KEYS[k]); has = true; 118 }); 119 if (!has) return saved || {}; 120 /* page_path ë ì¬ë¬ê·¸ë¡ ì ê·ííë¤ (§4.3) â cta.js ë íì¼ ê²½ë¡ë¥¼ ë³´ë¸ë¤ */ 121 if (out.page_path) { 122 out.page_path = out.page_path 123 .replace(/^\/(index\.html)?$/, "/") 124 .replace(/^\/usecase-([a-z-]+)\.html$/, "/usecases/$1") 125 .replace(/\.html$/, ""); 126 } 127 // storageê° ë§íë íì© URL í¤ cta_textì ë´ê¸´ ì í ë°ëª¨ëª ì¼ë¡ ìë³ì를 ë³µìíë¤.
128 if (out.intent === "demo_request" && !out.demo_name && out.cta_text) { 129 out.demo_name = out.cta_text.slice(0, CTA_KEYS.demo_name); 130 out.demo_id = out.cta_text.replace(/^AI\s*/, "").trim().replace(/[·\s]+/g, "-") 131 .replace(/[^0-9a-zA-Zê°-í£-]/g, "").toLowerCase().slice(0, CTA_KEYS.demo_id); 132 } 133 try { sessionStorage.setItem("neona_cta", JSON.stringify(out)); } catch (e) {} 134 return out; 135 })(); 136 137 var q0 = new URLSearchParams(location.search); 138 // ë°ëª¨ ìì²(모ë¬Â·ë¬´ì ì¹´ë) â ì´ë¤ ë°ëª¨ì¸ì§ ë³´ì¬ì£¼ê³ 문ì ë´ì©ìë ë¨ê¸´ë¤ 139 // demo ë CTA_KEYS 를 ì ê±°ì¹ë¯ë¡ ì¬ê¸°ì ìë¥¸ë¤ â ì ì르면 message í리íì´ ë°±ìë 2000ì ì íì ë겨 422 ê° ëë¤ 140 var demoName = cta.demo_name || (q0.get("demo") || "").slice(0, 100) || (cta.intent === "demo_request" ? cta.demo_id : ""); 141 if (demoName) { 142 var badge = document.getElementById("demoBadge"); 143 if (badge) { 144 badge.style.display = "block"; 145 badge.querySelector("[data-demo-title]").textContent = demoName; 146 } 147 document.getElementById("f-message").value = "ìì² ë°ëª¨: " + demoName + "\n"; 148 } 149 /* ââ ë°ëª¨ ìì² ëª¨ë¬ìì ëì´ì¨ ì ë ¥ê° í리í (usecases.js ê° sessionStorage ë¡ ì´ì) ââ 150 * ê°ì¸ì ë³´ë 쿼리ì¤í¸ë§ì ì£ì§ ìëë¤ â ê°ì ì
150¤ë¦¬ì§ì´ë¼ sessionStorage ë¡ ì ë¬ëë¤. 151 * ëì(privacy)ë ì´ìíì§ ìëë¤: ì´ íì´ì§ìì ë¤ì ë°ìì¼ íë¤. */ 152 function applyDemoHandoff(pre) { 153 if (!pre) return; 154 [["name","f-name"],["company","f-company"],["email","f-email"],["phone","f-phone"]].forEach(function (m) { 155 var el = document.getElementById(m[1]); 156 if (pre[m[0]] && el && !el.value) el.value = String(pre[m[0]]).slice(0, 200); 157 }); 158 if (pre.message) { 159 var msgEl = document.getElementById("f-message"); 160 msgEl.value = (msgEl.value ? msgEl.value : "") + String(pre.message).slice(0, 1500); 161 } 162 } 163 if (demoToken && window.BroadcastChannel) { 164 try { 165 var handoffChannel = new BroadcastChannel("neona_demo_handoff:" + demoToken); 166 handoffChannel.addEventListener("message", function (event) { 167 var message = event && event.data; 168 if (!message || message.type !== "response") return; 169 applyDemoHandoff(message.data); 170 handoffChannel.close(); 171 }); 172 handoffChannel.postMessage({ type: "request" }); 173 setTimeout(function () { try { handoffChannel.close(); } catch (e) {} }, 5000); 174 } catch (e) { /* channel unavailable â CTA demo context remains, only PII prefill is skipped */ } 175 } 176 177 var btn = document.getElementById("submitBtn"); 178 var msg = document.getElementById("formMsg"); 179 180 /* ââ ì°ë½ì²: ì«ìë§ ë°ê³ íì´íì ìëì¼ë¡ âââââââââââââââââââââââââââââââ 181 * ìì¸(02-)·í´ëí°/ì§ì(0XX-)·ëíë²í¸(15XX~19XX-XXXX)를 ì릿ìë¡ êµ¬ë¶íë¤. */ 182 function formatPhone(v) { 183 var d = v.replace(/\D/g, "").slice(0, 11); 184 if (d.indexOf("02") === 0) { 185 if (d.length <= 2) return d; 186 if (d.length <= 6) return d.slice(0, 2) + "-" + d.slice(2); 187 if (d.length <= 9) return d.slice(0, 2) + "-" + d.slice(2, d.length - 4) + "-" + d.slice(-4); 188 return d.slice(0, 2) + "-" + d.slice(2, 6) + "-" + d.slice(6, 10); 189 } 190 if (/^1[5-9]/.test(d)) { /* 1588 ê°ì ëíë²í¸ â 4-4 */ 191 return d.length <= 4 ? d : d.slice(0, 4) + "-" + d.slice(4, 8); 192 } 193 if (d.length <= 3) return d; 194 if (d.length <= 7) return d.slice(0, 3) + "-" + d.slice(3); 195 if (d.length <= 10) return d.slice(0, 3) + "-" + d.slice(3, d.length - 4) + "-" + d.slice(-4); 196 return d.slice(0, 3) + "-" + d.slice(3, 7) + "-" + d.slice(7, 11); 197 } 198 var phoneEl = document.getElementById("f-phone"); 199 phoneEl.addEventListener("input", function () { 200 var digitsBeforeCaret = phoneEl.value.slice(0, phoneEl.selectionStart).replace(/\D/g, "").length; 201 phoneEl.value = formatPhone(phoneEl.value); 202 /* 커ì를 "ëª ë²ì§¸ ì«ì ë¤"ìëì§ ê¸°ì¤ì¼ë¡ ë³µì â ì¤ê° ìì ì ëì¼ë¡ íì§ ìê² */ 203 var pos = 0, seen = 0; 204 while (pos < phoneEl.value.length && seen < digitsBeforeCaret) { 205 if (/\d/.test(phoneEl.value[pos])) seen++; 206 pos++; 207 } 208 phoneEl.setSelectionRange(pos, pos); 209 }); 210 211 function fail(text) { 212 msg.textContent = text; 213 msg.className = "msg error"; 214 btn.disabled = false; 215 } 216 217 form.addEventListener("submit", function (e) { 218 e.preventDefault(); 219 msg.className = "msg"; 220 var name = document.getElementById("f-name").value.trim(); 221 var email = document.getElementById("f-email").value.trim(); 222 // ì°ë½ì²ë íìë¤ â ìì ì´ ì²« íµí를 걸ì´ì¼ íë¤. ë°±ìëë ë¹ ê°ì ê±°ë¶íë¯ë¡ 223 // ì¬ê¸°ì ë§ì§ ìì¼ë©´ 422 ê° ê·¸ëë¡ ì¬ì©ììê² ë³´ì¸ë¤. 224 var phone = document.getElementById("f-phone").value.trim(); 225 // íì¬ëª ë íìë¤ â ìì ìë¦¼ì´ íì¬ëª ì¼ë¡ ë§ë¤ì´ì§ë¤. ë°±ìëë ë¹ ê°ì ê±°ë¶íë¤. 226 var company = document.getElementById("f-company").value.trim(); 227 if (!name || !email || !company || !phone) return fail("ì´ë¦Â·ì´ë©ì¼Â·íì¬ëª ·ì°ë½ì²ë¥¼ ì ë ¥í´ì£¼ì¸ì."); 228 // ëíë²í¸(8ì리)~í´ëí°(11ì리) â ê·¸ë³´ë¤ ì§§ì¼ë©´ ì°ë½ ë¶ê°ë¥í ê°ì´ë¤ 229 if (phone.replace(/\D/g, "").length < 8) return fail("ì°ë½ì²ë¥¼ ì íí ì ë ¥í´ì£¼ì¸ì."); 230 if (!document.getElementById("f-privacy").checked) return fail("ê°ì¸ì ë³´ ìì§Â·ì´ì©ì ëìí´ì£¼ì¸ì."); 231 btn.disabled = true; 232 233 var source = "landing:" + (new URLSearchParams(location.search).get("source") || "direct"); 234 fetch(API_ROOT + "/api/v1/inquiries/", { 235 method: "POST", 236 headers: { "Content-Type": "application/json" }, 237 body: JSON.stringify({ 238 name: name, 239 email: email, 240 company: company, 241 phone: phone, 242 inquiry_type: document.getElementById("f-inquiry-type").value, 243 message: document.getElementById("f-message").value.trim(), 244 privacy_agreed: true, 245 source: source.slice(0, 50), 246 // CTA ë§¥ë½ (CTA-LINKS §4.1·4.5) â ê°ì´ ìë í¤ë§ ë¶ëë¤ 247 ...cta, 248 // §3.3 ìº íì¸ ê·ì â íì¬ URLê³¼ í©ì¹ì§ ìê³ consent-gated first-touch
249 // ì ì¥ë¶ë§ ë³´ë¸ë¤. ê·¸ëì¼ íì contact URLì ê´ê³ IDê° ê¸°ì¡´ ìº íì¸ì ìì´ì§ ìëë¤. 250 ...(window.neonaAttribution ? window.neonaAttribution() : {}) 251 }) 252 }).then(function (res) { 253 if (res.status === 201) { 254 form.style.display = "none"; 255 document.getElementById("successPanel").style.display = "block"; 256 return; 257 } 258 if (res.status === 429) return fail("ìì²ì´ ë§ì ì ì í ë¤ì ìëí´ì£¼ì¸ì."); 259 return fail("ì ì¡ì ì¤í¨íìµëë¤. ì ë ¥ ë´ì©ì íì¸íê±°ë ì ì í ë¤ì ìëí´ì£¼ì¸ì."); 260 }).catch(function () { 261 fail("ë¤í¸ìí¬ ì¤ë¥ê° ë°ìíìµëë¤. ì ì í ë¤ì ìëí´ì£¼ì¸ì."); 262 }); 263 }); 264})(); 265</script>
265 266</body> 267</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.