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"> 6 7 <title>Apply for early access â Line</title> 8 <meta name="description" content="Apply for early access to Line. Share your property details and schedule an intro call."> 9 <link rel="canonical" href="https://withline.io/start/getstarted.html"> 10 <meta name="robots" content="index,follow,max-snippet:-1,max-image-preview:large,max-video-preview:-1"> 11 12 <!-- Open Graph --> 13 <meta property="og:type" content="website"> 14 <meta property="og:site_name" content="Line"> 15 <meta property="og:locale" content="en_US"> 16 <meta property="og:url" content="https://withline.io/start/getstarted.html"> 17 <meta property="og:title" content="Apply for early access â Line"> 18 <meta property="og:description" content="Apply for early access to Line. Share your property details and schedule an intro call."> 19 <meta property="og:image" content="https://withline.io/images/line-logo.png"> 20 <meta property="og:image:width" content="512"> 21 <meta property="og:image:height" content="512"> 22 23 <!-- Twitter --> 24 <meta name="twitter:card" content="summary"> 25 <meta name="twitter:title" content="Apply for early access â Line"> 26 <meta name="twitter:description" content="Apply for early access to Line. Share your property details and schedule an intro call."> 27 <meta name="twitter:image" content="https://withline.io/images/line-logo.png"> 28 <meta name="twitter:image:alt" content="Line logo"> 29 30 <!-- Styles & Fonts --> 31 <link rel="stylesheet" href="../style.css"> 32 <link rel="preconnect" href="https://fonts.googleapis.com"> 33 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 34 <link href="https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,300;0,400;0,500;0,600;0,700;1,300;1,400;1,500;1,600;1,700&display=swap" rel="stylesheet"> 35 36 <!-- Icons --> 37 <link rel="apple-touch-icon" sizes="180x180" href="../images/favicon/apple-icon-180x180.png"> 38 <link rel="icon" type="image/svg+xml" href="../images/favicon/favicon.svg"> 39 <link rel="icon" type="image/png" sizes="32x32" href="../images/favicon/favicon-32x32.png"> 40 <link rel="icon" type="image/png" sizes="16x16" href="../images/favicon/favicon-16x16.png"> 41 <link rel="manifest" href="../images/favicon/manifest.json"> 42 <meta name="theme-color" content="#ffffff"> 43 <style> 44 /* Override logo filter for pro page since we're using black fills directly */ 45 .logo svg { 46 filter: none !important; 47 } 48 </style> 49</head> 50<body> 51 <nav class="main-nav"> 52 <div class="nav-container"> 53 <a href="../index.html" class="logo" aria-label="Line home"> 54 <svg xmlns="http://www.w3.org/2000/svg" width="54" height="19" viewBox="0 0 54 19" fill="none"> 55 <g clip-path="url(#clip0_pro)"> 56 <mask id="mask0_pro" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="54" height="19"> 57 <path d="M54 0H0V19H54V0Z" fill="white"/> 58 </mask> 59 <g mask="url(#mask0_pro)"> 60 <path d="M21.8806 15V3.36367H24.6931V12.7159H29.534V15H21.8806ZM30.67 15V6.27275H33.4484V15H30.67ZM32.062 5.25571C31.6719 5.25571 31.3366 5.12691 31.0563 4.86934C30.776 4.60797 30.6359 4.29359 30.6359 3.92617C30.6359 3.56253 30.776 3.25191 31.0563 2.99434C31.3366 2.73297 31.6719 2.60229 32.062 2.60229C32.4559 2.60229 32.7912 2.73297 33.0677 2.99434C33.348 3.25191 33.4881 3.56253 33.4881 3.92617C33.4881 4.29359 33.348 4.60797 33.0677 4.86934C32.7912 5.12691 32.4559 5.25571 32.062 5.25571ZM37.6752 10.0227V15H34.8968V6.27275H37.5389V7.87502H37.6355C37.8286 7.34093 38.1582 6.92237 38.6241 6.61934C39.09 6.31252 39.6449 6.15912 40.2889 6.15912C40.9025 6.15912 41.4347 6.29738 41.8855 6.57389C42.34 6.84662 42.6923 7.22919 42.9423 7.72161C43.1961 8.21025 43.3211 8.78222 43.3173 9.43752V15H40.5389V9.98298C40.5427 9.49814 40.4196 9.11934 40.1696 8.84661C39.9233 8.57388 39.5805 8.43752 39.1411 8.43752C38.8495 8.43752 38.5919 8.50191 38.3684 8.6307C38.1487 8.7557 37.9783 8.93564 37.8571 9.17048C37.7396 9.40533 37.679 9.68942 37.6752 10.0227ZM48.797 15.1648C47.8841 15.1648 47.0962 14.9848 46.4334 14.625C45.7743 14.2614 45.2667 13.7443 44.9106 13.0739C44.5584 12.3996 44.3822 11.5985 44.3822 10.6705C44.3822 9.76896 44.5603 8.98108 44.9163 8.30684C45.2724 7.62881 45.7743 7.10229 46.422 6.72729C47.0697 6.3485 47.833 6.15912 48.7118 6.15912C49.333 6.15912 49.9012 6.25571 50.4163 6.44889C50.9315 6.64208 51.3765 6.92805 51.7515 7.30684C52.1265 7.68563 52.4182 8.15343 52.6265 8.71025C52.8349 9.26328 52.939 9.89775 52.939 10.6136V11.3068H45.3538V9.6932H50.3538C50.35 9.39775 50.28 9.13449 50.1436 8.90343C50.0072 8.67237 49.8197 8.49244 49.5811 8.36366C49.3462 8.23108 49.0754 8.16479 48.7686 8.16479C48.458 8.16479 48.1796 8.23487 47.9334 8.37502C47.6872 8.51138 47.4921 8.69888 47.3481 8.93752C47.2042 9.17237 47.1284 9.43941 47.1209 9.73866V11.3807C47.1209 11.7367 47.1909 12.0492 47.3311 12.3182C47.4712 12.5833 47.6701 12.7898 47.9277 12.9375C48.1853 13.0852 48.4921 13.1591 48.8481 13.1591C49.0944 13.1591 49.3178 13.125 49.5186 13.0568C49.7194 12.9886 49.8917 12.8883 50.0356 12.7557C50.1796 12.6231 50.2875 12.4602 50.3595 12.267L52.9106 12.3409C52.8046 12.9129 52.5716 13.411 52.2118 13.8352C51.8557 14.2557 51.3879 14.5833 50.8084 14.8182C50.2288 15.0492 49.5584 15.1648 48.797 15.1648Z" fill="#121212"/> 61 <path d="M10.8574 2.85693L17.9093 15.0712H3.80542L10.8574 2.85693Z" fill="#121212"/> 62 <path d="M5.42857 6.92822L10.1299 15.0711H0.727295L5.42857 6.92822Z" fill="#121212"/> 63 </g> 64 </g> 65 <defs> 66 <clipPath id="clip0_pro"> 67 <rect width="54" height="19" fill="white"/> 68 </clipPath> 69 </defs> 70 </svg> 71 </a> 72 <div class="nav-contact"> 73 <p style="margin: 0; font-size: clamp(0.75rem, 1vw, 0.85rem); color: var(--text-color);"><strong>Questions?</strong> Email <a href="mailto:[email protected]" style="color: var(--primary-color); text-decoration: underline; text-underline-offset: 3px;">[email protected]</a></p> 74 </div> 75 </div> 76 </nav> 77 78 <main> 79 <section class="testimonial-section" style="background-color: white !important; padding-top: 120px;"> 80 <div class="testimonial-content"> 81 <div style="max-width: 600px; margin: 0 auto;"> 82 <div style="text-align: center; margin-bottom: 32px;"> 83 <h2 style="font-size: clamp(2rem, 3.5vw, 2.5rem); font-weight: 700; margin-bottom: 0.75rem; color: var(--primary-color);">Apply for early access</h2> 84 </div> 85 86 <!-- Two-step visual indicator --> 87 <div style="margin: 1rem 0 1.5rem 0;"> 88 <div class="step-indicator" style="display: flex; align-items: center; gap: 0.75rem; font-size: 0.875rem; justify-content: center;">
89 <span style="color: var(--primary-color); font-weight: 600;">Step 1: Share details</span> 90 <span class="step-line" style="flex: 1; height: 1px; background-color: #e5e5e5; display: block;" aria-hidden="true"></span> 91 <span style="color: rgba(0, 0, 0, 0.6); font-weight: 400;">Step 2: Schedule intro call</span> 92 </div> 93 </div> 94 95 <style> 96 @media (max-width: 640px) { 97 .step-indicator { 98 flex-direction: column !important; 99 gap: 0.5rem !important; 100 } 101 .step-indicator .step-line { 102 width: 1px !important; 103 height: 12px !important; 104 flex: none !important; 105 } 106 } 107 </style> 108 109 <form id="pro-onboarding-form" class="onboarding-form" action="https://formspree.io/f/mpwokood" method="POST" data-redirect="getstarted/thanks.html" style="margin: 0;"> 110 <div class="form-field"> 111 <label for="name">Name</label> 112 <input type="text" id="name" name="name" required autocomplete="name" /> 113 <span class="error-message" id="name-error"></span> 114 </div> 115 116 <div class="form-field"> 117 <label for="email">Email</label> 118 <input type="email" id="email" name="email" required autocomplete="email" /> 119 <span class="error-message" id="email-error"></span> 120 </div> 121 122 <div class="form-field"> 123 <label for="website">Website</label> 124 <input type="url" id="website" name="website" autocomplete="url" placeholder="https://example.com" /> 125 <span class="error-message" id="website-error"></span> 126 </div> 127 128 <div class="form-field"> 129 <label for="primary_goal">What are your goals for your property?</label> 130 <input type="text" id="primary_goal" name="primary_goal" autocomplete="off" /> 131 <span class="error-message" id="primary_goal-error"></span> 132 </div> 133 134 <!-- Hidden fields --> 135 <input type="hidden" name="plan" value="Pro" /> 136 <input type="hidden" name="source" value="pricing" /> 137 138 <!-- Honeypot --> 139 <input type="text" name="company" style="display: none;" tabindex="-1" autocomplete="off" /> 140 141 <button type="submit" class="onboarding-submit-btn">Continue</button> 142 </form> 143 </div> 144 </div> 145 </section> 146 </main> 147 148 <footer> 149 <p>© 2026 With Line, Inc. All rights reserved.</p> 150 </footer> 151 152
152<script src="../script.js"></script>
152 153
153<script> 154 (function() { 155 // Extract UTM parameters from URL and add as hidden inputs 156 const urlParams = new URLSearchParams(window.location.search); 157 const utmParams = ['utm_source', 'utm_medium', 'utm_campaign']; 158 utmParams.forEach(param => { 159 if (urlParams.has(param)) { 160 const input = document.createElement('input'); 161 input.type = 'hidden'; 162 input.name = param; 163 input.value = urlParams.get(param); 164 document.getElementById('pro-onboarding-form').appendChild(input); 165 } 166 }); 167 168 const form = document.getElementById('pro-onboarding-form'); 169 const emailInput = document.getElementById('email'); 170 const websiteInput = document.getElementById('website'); 171 const primaryGoalInput = document.getElementById('primary_goal'); 172 173 // Validation functions 174 function validateEmail(email) { 175 const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 176 return re.test(email); 177 } 178 179 function validateURL(url) { 180 if (!url) return false; 181 try { 182 // Try to parse as-is 183 let urlObj = new URL(url); 184 return urlObj.protocol === 'http:' || urlObj.protocol === 'https:'; 185 } catch { 186 // If parsing fails, try adding https:// 187 try { 188 const urlObj = new URL('https://' + url); 189 return true; 190 } catch { 191 return false; 192 } 193 } 194 } 195 196 function normalizeURL(url) { 197 if (!url) return url; 198 try { 199 new URL(url); 200 return url; // Already has protocol 201 } catch { 202 return 'https://' + url; // Add protocol 203 } 204 } 205 206 function showError(fieldId, message) { 207 const errorEl = document.getElementById(fieldId + '-error'); 208 if (errorEl) { 209 errorEl.textContent = message; 210 errorEl.style.display = 'block'; 211 } 212 const field = document.getElementById(fieldId); 213 if (field) { 214 field.classList.add('error'); 215 } 216 } 217 218 function clearError(fieldId) { 219 const errorEl = document.getElementById(fieldId + '-error'); 220 if (errorEl) { 221 errorEl.textContent = ''; 222 errorEl.style.display = 'none'; 223 } 224 const field = document.getElementById(fieldId); 225 if (field) { 226 field.classList.remove('error'); 227 } 228 } 229 230 // Real-time validation 231 emailInput.addEventListener('blur', function() { 232 if (this.value && !validateEmail(this.value)) { 233 showError('email', 'Please enter a valid email address'); 234 } else { 235 clearError('email'); 236 } 237 }); 238 239 // Optional field validation (only if filled) 240 websiteInput.addEventListener('blur', function() { 241 if (this.value && !validateURL(this.value)) { 242 showError('website', 'Please enter a valid URL'); 243 } else { 244 clearError('website'); 245 } 246 }); 247 248 form.addEventListener('submit', async function(e) { 249 e.preventDefault(); 250 251 // Clear previous errors 252 ['name', 'email', 'website'].forEach(fieldId => clearError(fieldId)); 253 254 // Check honeypot 255 const honeypot = form.querySelector('input[name="company"]'); 256 if (honeypot && honeypot.value) { 257 return; // Silent fail for bots 258 } 259 260 // Validate - only name and email are required 261 let isValid = true; 262 263 const nameInput = document.getElementById('name'); 264 if (!nameInput.value || !nameInput.value.trim()) { 265 showError('name', 'Please enter your name'); 266 isValid = false;
267 } 268 269 if (!emailInput.value || !validateEmail(emailInput.value)) { 270 showError('email', 'Please enter a valid email address'); 271 isValid = false; 272 } 273 274 // Optional: validate website if provided 275 if (websiteInput.value && !validateURL(websiteInput.value)) { 276 showError('website', 'Please enter a valid URL'); 277 isValid = false; 278 } 279 280 if (!isValid) { 281 return; 282 } 283 284 // Normalize URL before submitting (only if provided) 285 if (websiteInput.value) { 286 const normalizedURL = normalizeURL(websiteInput.value); 287 if (normalizedURL !== websiteInput.value) { 288 websiteInput.value = normalizedURL; 289 } 290 } 291 292 // Save email to sessionStorage 293 sessionStorage.setItem('lineEmail', emailInput.value); 294 295 // Submit to Formspree 296 const formData = new FormData(form); 297 298 try { 299 const response = await fetch(form.action, { 300 method: 'POST', 301 body: formData, 302 headers: { 'Accept': 'application/json' } 303 }); 304 305 if (response.ok) { 306 // Redirect to thank you page 307 window.location.href = 'getstarted/thanks.html'; 308 } else { 309 const data = await response.json(); 310 if (data.errors) { 311 alert('There was an error submitting the form. Please try again.'); 312 } 313 } 314 } catch (error) { 315 console.error('Error:', error); 316 alert('There was an error submitting the form. Please try again.'); 317 } 318 }); 319 })(); 320 </script>
320 321</body> 322</html> 323
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.