PageSourceSearch

https://withline.io/start/getstarted.html

html withline.io collected 2026-10-08 07:04:11 UTC 17,534 bytes, 323 lines download raw bytes

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.