1/*! 2 * IKON Refund Program â embeddable customer notice 3 * Stephen Wade Auto Center 4 * 5 * This single script renders the entire IKON Refund Program page. It is used 6 * by /ikon-refund-program on stephenwade.com and can be embedded on any other 7 * dealership website with two lines: 8 * 9 * <div id="ikon-refund-program"></div> 10 * <script src="https://www.stephenwade.com/ikon-refund-program.js" async></script> 11 * 12 * Optional attributes on the <script> tag: 13 * data-accent="#314259" brand color for headings and buttons 14 * data-questionnaire="https://..." override the questionnaire download URL 15 * 16 * The questionnaire itself is hosted in S3 (see CONFIG.questionnaire.url), 17 * not in this repository. 18 * 19 * ALL program copy lives in CONFIG below so there is one source of truth for 20 * the Division-approved wording. Values in [SQUARE BRACKETS] are placeholders. 21 * Before publication: replace every placeholder and set CONFIG.draft to false. 22 * 23 * Nothing on this page collects or submits information. There are no forms. 24 */ 25(function () { 26 'use strict'; 27 28 var currentScript = document.currentScript; 29 30 var CONFIG = { 31 // Shows a review banner and highlights placeholders. Set to false to publish. 32 draft: false, 33 34 programName: 'IKON Refund Program', 35 groupName: 'Stephen Wade Auto Center', 36 productName: 'IKON Connection Car Technology product ("IKON")', 37 eligibilityStart: 'July 7, 2023', 38 eligibilityEnd: 'October 30, 2024', 39 responseWindowDays: '180', 40 refundIssueDays: '30', 41 42 // Hosted in S3. Replace with the Division-approved questionnaire when final. 43 questionnaire: { 44 url: 'https://swac-pdfs.s3.us-west-2.amazonaws.com/IKON-Refund/ikon-form.pdf', 45 buttonLabel: 'Download the Refund Questionnaire (PDF)' 46 }, 47 48 // Consent Order para. 10.c: the page must prominently display a designated 49 // point of contact with a name, phone number, email address, and physical 50 // address. Replace every bracketed value. 51 contact: { 52 name: '[CONTACT NAME OR TEAM NAME]', 53 phone: '[DEDICATED PHONE NUMBER]', 54 email: '[DEDICATED EMAIL ADDRESS]', 55 address: '150 West Auto Mall Drive, St. George, UT 84770', 56 hours: '[HOURS, e.g. Monday to Friday, 9:00 AM to 5:00 PM]' 57 }, 58 59 // Consent Order para. 10.c: the page must prominently display the 60 // designated webpage hosted by the Division. Get the URL from the Division. 61 division: { 62 name: 'Utah Division of Consumer Protection', 63 programUrl: '[DIVISION PROGRAM WEBPAGE URL]', 64 siteLabel: 'dcp.utah.gov', 65 siteUrl: 'https://dcp.utah.gov', 66 phone: '801-530-6601' 67 }, 68 69 // Drop-off locations. Names follow the dealerships listed in the Order. 70 dealerships: [ 71 { name: 'Stephen Wade Toyota', address: '150 Auto Mall Dr, St. George, UT 84770', phone: '435-253-6873' }, 72 { name: 'Stephen Wade Honda', address: '1630 Auto Mall Dr, St. George, UT 84770', phone: '435-409-4574' }, 73 { name: 'Stephen Wade Mazda', address: '1630 Auto Mall Dr, St. George, UT 84770', phone: '435-409-4574' }, 74 { name: 'Stephen Wade Nissan', address: '230 Auto Mall Dr, St. George, UT 84770', phone: '435-634-4522' }, 75 { name: 'Stephen Wade Chrysler Jeep Dodge Ram', address: '1724 S Auto Mall Dr, St. George, UT 84770', phone: '435-634-4200' }, 76 { name: 'Stephen Wade Cadillac', address: '1670 Auto Mall Dr, St. George, UT 84770', phone: '435-986-7996' }, 77 { name: 'Mercedes-Benz of St. George', address: '1792 S Black Ridge Dr, St. George, UT 84770', phone: '435-634-7533' }, 78 { name: 'Orem Toyota', address: '1400 Sandhill Rd, Orem, UT 84058', phone: '801-823-6020' } 79 ] 80 }; 81 82 // --------------------------------------------------------------------------- 83 // Styles (scoped under .ikrp so they never leak into a host site) 84 // --------------------------------------------------------------------------- 85 var CSS = [ 86 '.ikrp{--ikrp-accent:#314259;--ikrp-ink:#1c2430;--ikrp-muted:#5b6673;--ikrp-line:#dde2e8;--ikrp-tint:#eef2f7;--ikrp-bg:#ffffff;', 87 'box-sizing:border-box;max-width:880px;margin:0 auto;padding:32px 20px 56px;color:var(--ikrp-ink);font-family:inherit;line-height:1.55;font-size:17px;text-align:left}', 88 '.ikrp *,.ikrp *::before,.ikrp *::after{box-sizing:inherit}', 89 '.ikrp h1,.ikrp h2,.ikrp h3{margin:0 0 .5em;line-height:1.2;color:var(--ikrp-accent);font-weight:700}', 90 '.ikrp h1{font-size:2.1rem}.ikrp h2{font-size:1.4rem;margin-top:0}.ikrp h3{font-size:1.1rem}', 91 '.ikrp p{margin:0 0 1em}.ikrp p:last-child{margin-bottom:0}', 92 '.ikrp ul,.ikrp ol{margin:0 0 1em;padding-left:1.4em}.ikrp li{margin:0 0 .5em}', 93 '.ikrp a{color:var(--ikrp-accent);text-decoration:underline;text-underline-offset:2px}', 94 '.ikrp-eyebrow{font-size:.85rem;letter-spacing:.08em;text-transform:uppercase;color:var(--ikrp-muted);font-weight:700;margin:0 0 .6em}', 95 '.ikrp-lede{font-size:1.15rem;color:var(--ikrp-ink);max-width:62ch}', 96 '.ikrp-section{background:var(--ikrp-bg);border:1px solid var(--ikrp-line);border-radius:12px;padding:24px;margin:20px 0}', 97 '.ikrp-section--prominent{background:var(--ikrp-tint);border-color:var(--ikrp-accent);border-left-width:6px}', 98 '.ikrp-options{display:grid;grid-template-columns:1fr;gap:14px;margin:0 0 1em}', 99 '.ikrp-option{border:1px solid var(--ikrp-line);border-radius:10px;padding:16px 18px;background:#fbfcfd}', 100 '.ikrp-option h3{margin-bottom:.35em}.ikrp-option p{margin:0;color:var(--ikrp-ink)}', 101 '.ikrp-steps{counter-reset:ikrp-step;list-style:none;padding:0;margin:0 0 1em}', 102 '.ikrp-steps li{position:relative;padding-left:52px;margin:0 0 18px;min-height:40px}', 103 '.ikrp-steps li::before{counter-increment:ikrp-step;content:counter(ikrp-step);position:absolute;
103left:0;top:0;width:36px;height:36px;border-radius:50%;', 104 'background:var(--ikrp-accent);color:#fff;font-weight:700;display:flex;align-items:center;justify-content:center;font-size:1rem}', 105 '.ikrp-steps li strong{display:block;margin-bottom:.2em}', 106 '.ikrp-button{display:inline-block;background:var(--ikrp-accent);color:#fff !important;text-decoration:none !important;font-weight:700;font-size:1.05rem;', 107 'padding:14px 22px;border-radius:8px;margin:6px 0 4px;line-height:1.2}', 108 '.ikrp-button:hover,.ikrp-button:focus{filter:brightness(1.12);outline:3px solid rgba(49,66,89,.35);outline-offset:2px}', 109 '.ikrp-button--secondary{background:#fff;color:var(--ikrp-accent) !important;border:2px solid var(--ikrp-accent)}', 110 '.ikrp-note{font-size:.95rem;color:var(--ikrp-muted);margin-top:.6em}', 111 '.ikrp-callout{border:1px solid var(--ikrp-line);border-radius:10px;background:#fff8e6;padding:12px 16px;font-size:.98rem}', 112 '.ikrp-contact{display:grid;grid-template-columns:1fr;gap:10px 20px;margin:0}', 113 '.ikrp-contact div{margin:0}.ikrp-contact dt{font-size:.8rem;text-transform:uppercase;letter-spacing:.06em;color:var(--ikrp-muted);font-weight:700}', 114 '.ikrp-contact dd{margin:2px 0 0;font-size:1.05rem}', 115 '.ikrp-dealers{display:grid;grid-template-columns:1fr;gap:12px;list-style:none;padding:0;margin:0}', 116 '.ikrp-dealers li{border:1px solid var(--ikrp-line);border-radius:10px;padding:14px 16px;margin:0;background:#fbfcfd}', 117 '.ikrp-dealers strong{display:block;margin-bottom:2px}.ikrp-dealers span{display:block;color:var(--ikrp-ink);font-size:.98rem}', 118 '.ikrp-placeholder{background:#fff2a8;color:#5a4a00;padding:0 .3em;border-radius:4px;font-weight:700}', 119 '.ikrp-draft{background:#fff2a8;border:1px solid #e6c95c;color:#5a4a00;border-radius:10px;padding:12px 16px;margin:0 0 20px;font-size:.95rem}', 120 '.ikrp-footer{font-size:.9rem;color:var(--ikrp-muted);margin-top:28px;text-align:center}', 121 '@media (min-width:640px){.ikrp-options{grid-template-columns:1fr 1fr}.ikrp-contact{grid-template-columns:1fr 1fr}.ikrp-dealers{grid-template-columns:1fr 1fr}}', 122 '@media print{.ikrp-button{border:2px solid #000;color:#000 !important;background:#fff}.ikrp-draft{display:none}}' 123 ].join(''); 124 125 // --------------------------------------------------------------------------- 126 // Tiny DOM helpers 127 // --------------------------------------------------------------------------- 128 var PLACEHOLDER = /\[[^\]]+\]/; 129 130 function h(tag, attrs, children) { 131 var el = document.createElement(tag); 132 if (attrs) { 133 for (var k in attrs) { 134 if (!Object.prototype.hasOwnProperty.call(attrs, k)) continue; 135 if (k === 'class') el.className = attrs[k]; 136 else el.setAttribute(k, attrs[k]); 137 } 138 } 139 if (children) { 140 for (var i = 0; i < children.length; i++) { 141 var c = children[i]; 142 if (c === null || c === undefined) continue; 143 el.appendChild(typeof c === 'string' ? document.createTextNode(c) : c); 144 } 145 } 146 return el; 147 } 148 149 // Text that may still be a placeholder. Highlighted while CONFIG.draft is true. 150 function val(text) { 151 if (CONFIG.draft && PLACEHOLDER.test(text)) return h('mark', { 'class': 'ikrp-placeholder' }, [text]); 152 return document.createTextNode(text); 153 } 154 155 function telHref(phone) { 156 return 'tel:' + String(phone).replace(/[^0-9+]/g, ''); 157 } 158 159 function isPlaceholder(text) { 160 return PLACEHOLDER.test(text); 161 } 162 163 // --------------------------------------------------------------------------- 164 // Sections 165 // --------------------------------------------------------------------------- 166 function renderDraftBanner() { 167 if (!CONFIG.draft) return null; 168 return h('div', { 'class': 'ikrp-draft', role: 'status' }, [ 169 h('strong', null, ['Draft for review. ']), 170 'Highlighted items are placeholders that must be replaced before this page is published.' 171 ]); 172 } 173 174 function renderIntro() { 175 return h('header', null, [ 176 h('p', { 'class': 'ikrp-eyebrow' }, [CONFIG.groupName]), 177 h('h1', null, [CONFIG.programName]), 178 h('p', { 'class': 'ikrp-lede' }, [ 179 'If an ' + CONFIG.productName + ' was added to a vehicle you purchased or leased from a ' + 180 CONFIG.groupName + ' dealership between ' + CONFIG.eligibilityStart + ' and ' + CONFIG.eligibilityEnd + 181 ', you may request a refund of the IKON purchase price.' 182 ]) 183 ]); 184 } 185 186 function renderAbout() { 187 return h('section', { 'class': 'ikrp-section', 'aria-labelledby': 'ikrp-about' }, [ 188 h('h2', { id: 'ikrp-about' }, ['About this program']), 189 h('p', null, [ 190 'IKON is a GPS device attached to your vehicle that may help with vehicle recovery in the event of theft, ' + 191 'along with other location-based features. The purchase of IKON is optional and is not required to buy or lease ' + 192 'a vehicle from any of our dealerships.' 193 ]), 194 h('p', null, [ 195 'If you did not want to purchase IKON with your vehicle, you may request a refund through this program. ' + 196 'You can choose to have the IKON device removed from your vehicle at no cost, or to keep it.' 197 ]), 198 h('p', null, ['Eligible customers are also being notified by mail and email.']) 199 ]); 200 } 201 202 function renderEligibility() { 203 return h('section', { 'class': 'ikrp-section', 'aria-labelledby': 'ikrp-eligibility' }, [ 204 h('h2', { id: 'ikrp-eligibility' }, ['Who is eligible']), 205 h('p', null, ['You may be eligible if all of the following apply:']), 206 h('ul', null, [ 207 h('li', null, ['You purchased or leased a vehicle from one of the dealerships listed on this page.']), 208 h('li', null, ['The purchase or lease took place between ' + CONFIG.eligibilityStart + ' and ' + CONFIG.eligibilityEnd + '.']), 209 h('li', null, ['An IKON product was added to that vehicle as part of the transaction.']) 210 ]), 211 h('div', { 'class': 'ikrp-callout' }, [ 212 h('strong', null, ['Not eligible: ']), 213 'If your vehicle was stolen and later recovered using IKONâs GPS tracking services, you are not eligible for a refund under this program.' 214 ]), 215 h('p', { 'class': 'ikrp-note' }, [ 216 'Completed questionnaires must be returned within ' + CONFIG.responseWindowDays + ' days. Your notice letter describes the deadline that applies to you.' 217 ]) 218 ]); 219 } 220 221 function renderOptions() { 222 return h('section', { 'class': 'ikrp-section', 'aria-labelledby': 'ikrp-options' }, [ 223 h('h2', { id: 'ikrp-options' }, ['Your refund options']), 224 h('div', { 'class': 'ikrp-options' }, [ 225 h('div', { 'class': 'ikrp-option' }, [ 226 h('h3', null, ['Remove IKON']), 227 h('p', null, ['Receive a full refund of the price you paid for IKON. We will remove the device from your vehicle at no cost to you.']) 228 ]), 229 h('div', { 'class': 'ikrp-option' }, [ 230 h('h3', null, ['Keep IKON']), 231 h('p', null, ['Receive a refund of the price you paid for IKON minus the wholesale cost of the IKON device.']) 232 ]) 233 ]), 234 h('p', null, [ 235 'Refunds are issued by check or ACH bank transfer, whichever you choose on the questionnaire, within ' + 236 CONFIG.refundIssueDays + ' days after we receive your completed questionnaire. Refunds are not issued as store credit, gift cards, or services.' 237 ]) 238 ]); 239 } 240
241 function renderSteps(questionnaireUrl) { 242 return h('section', { 'class': 'ikrp-section', 'aria-labelledby': 'ikrp-steps' }, [ 243 h('h2', { id: 'ikrp-steps' }, ['How to request your refund']), 244 h('ol', { 'class': 'ikrp-steps' }, [ 245 h('li', null, [ 246 h('strong', null, ['Download and print the questionnaire.']), 247 h('a', { 'class': 'ikrp-button', href: questionnaireUrl, download: '', target: '_blank', rel: 'nofollow noopener' }, [CONFIG.questionnaire.buttonLabel]) 248 ]), 249 h('li', null, [ 250 h('strong', null, ['Complete every question.']), 251 'Choose how you would like to receive your refund (check or ACH bank transfer) and whether you want the IKON device removed.' 252 ]), 253 h('li', null, [ 254 h('strong', null, ['Bring the completed questionnaire to any of the dealerships listed below.']), 255 'If you received a questionnaire by mail, you may also return it using the prepaid envelope included with your letter.' 256 ]), 257 h('li', null, [ 258 h('strong', null, ['Receive your refund.']), 259 'If you asked to have IKON removed, the dealership will arrange the removal at no cost to you.' 260 ]) 261 ]), 262 h('div', { 'class': 'ikrp-callout' }, [ 263 h('strong', null, ['This page does not collect or submit any information. ']), 264 'Please do not send bank account details by email. Bring your completed questionnaire to a dealership in person.' 265 ]) 266 ]); 267 } 268 269 function renderContact() { 270 var c = CONFIG.contact; 271 var phone = isPlaceholder(c.phone) ? val(c.phone) : h('a', { href: telHref(c.phone) }, [c.phone]); 272 var email = isPlaceholder(c.email) ? val(c.email) : h('a', { href: 'mailto:' + c.email }, [c.email]); 273 return h('section', { 'class': 'ikrp-section ikrp-section--prominent', 'aria-labelledby': 'ikrp-contact' }, [ 274 h('h2', { id: 'ikrp-contact' }, ['Questions? Contact us']), 275 h('p', null, ['Our dedicated team can answer questions about the program, your eligibility, or the status of your refund.']), 276 h('dl', { 'class': 'ikrp-contact' }, [ 277 h('div', null, [h('dt', null, ['Contact']), h('dd', null, [val(c.name)])]), 278 h('div', null, [h('dt', null, ['Phone']), h('dd', null, [phone])]), 279 h('div', null, [h('dt', null, ['Email']), h('dd', null, [email])]), 280 h('div', null, [h('dt', null, ['Hours']), h('dd', null, [val(c.hours)])]), 281 h('div', null, [h('dt', null, ['Mailing address']), h('dd', null, [val(c.address)])]) 282 ]) 283 ]); 284 } 285 286 function renderDivision() { 287 var d = CONFIG.division; 288 var programLink = isPlaceholder(d.programUrl) 289 ? h('p', null, [h('strong', null, ['Program webpage: ']), val(d.programUrl)]) 290 : h('p', null, [h('a', { 'class': 'ikrp-button ikrp-button--secondary', href: d.programUrl, target: '_blank', rel: 'noopener' }, ['Visit the Divisionâs program page'])]); 291 return h('section', { 'class': 'ikrp-section ikrp-section--prominent', 'aria-labelledby': 'ikrp-division' }, [ 292 h('h2', { id: 'ikrp-division' }, [d.name]), 293 h('p', null, ['The ' + d.name + ' maintains a webpage about this program.']), 294 programLink, 295 h('p', null, [ 296 'You may also contact the Division at ', 297 h('a', { href: d.siteUrl, target: '_blank', rel: 'noopener' }, [d.siteLabel]), 298 ' or ', 299 h('a', { href: telHref(d.phone) }, [d.phone]), 300 '.' 301 ]) 302 ]); 303 } 304 305 function renderDealerships() { 306 var items = []; 307 for (var i = 0; i < CONFIG.dealerships.length; i++) { 308 var d = CONFIG.dealerships[i]; 309 var phone = isPlaceholder(d.phone) ? val(d.phone) : h('a', { href: telHref(d.phone) }, [d.phone]); 310 items.push(h('li', null, [ 311 h('strong', null, [d.name]), 312 h('span', null, [d.address]), 313 h('span', null, [phone]) 314 ])); 315 } 316 return h('section', { 'class': 'ikrp-section', 'aria-labelledby': 'ikrp-locations' }, [ 317 h('h2', { id: 'ikrp-locations' }, ['Where to bring your completed questionnaire']), 318 h('p', null, ['You may bring your questionnaire to any of these dealerships during business hours.']), 319 h('ul', { 'class': 'ikrp-dealers' }, items) 320 ]); 321 } 322 323 function renderFooter() { 324 return h('p', { 'class': 'ikrp-footer' }, [ 325 'This page is provided by ' + CONFIG.groupName + ' to help customers participate in the ' + CONFIG.programName + '. It does not collect or submit any information.' 326 ]); 327 } 328 329 // --------------------------------------------------------------------------- 330 // Mount 331 // --------------------------------------------------------------------------- 332 function ensureRobotsMeta() { 333 // Best effort for host sites that forget: ask search engines not to index 334 // the page this notice is rendered on. Hosts should still send an 335 // X-Robots-Tag header; this is a fallback, not a substitute. 336 if (document.querySelector('meta[name="robots"]')) return; 337 var meta = document.createElement('meta'); 338 meta.setAttribute('name', 'robots'); 339 meta.setAttribute('content', 'noindex, nofollow, noarchive, nosnippet'); 340 document.head.appendChild(meta); 341 } 342 343 function mount() { 344 var target = document.getElementById('ikon-refund-program'); 345 if (!target) { 346 target = document.createElement('div'); 347 target.id = 'ikon-refund-program'; 348 if (currentScript && currentScript.parentNode) currentScript.parentNode.insertBefore(target, currentScript.nextSibling); 349 else document.body.appendChild(target); 350 } 351 if (target.getAttribute('data-ikrp-mounted') === 'true') return; 352 target.setAttribute('data-ikrp-mounted', 'true'); 353 354 var accent = currentScript && currentScript.getAttribute('data-accent'); 355 var questionnaireOverride = currentScript && currentScript.getAttribute('data-questionnaire'); 356 var questionnaireUrl = questionnaireOverride || CONFIG.questionnaire.url; 357 358 if (!document.getElementById('ikrp-styles')) { 359 var style = document.createElement('style'); 360 style.id = 'ikrp-styles'; 361 style.appendChild(document.createTextNode(CSS)); 362 document.head.appendChild(style); 363 } 364 365 ensureRobotsMeta(); 366 367 var root = h('article', { 'class': 'ikrp', lang: 'en' }, [ 368 renderDraftBanner(), 369 renderIntro(), 370 renderAbout(), 371 renderEligibility(), 372 renderOptions(), 373 renderSteps(questionnaireUrl), 374 renderContact(), 375 renderDivision(), 376 renderDealerships(), 377 renderFooter() 378 ]); 379 if (accent) root.style.setProperty('--ikrp-accent', accent); 380 381 while (target.firstChild) target.removeChild(target.firstChild); 382 target.appendChild(root); 383 } 384 385 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', mount); 386 else mount(); 387})();
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.