LONTA TAP-TO-CALL LAB AND AUDITOR — v1 / 2026-10-24 OPEN WITHOUT INSTALLATION Save tap-to-call-auditor.html and double-click it in a modern browser. The tool is self-contained. It makes no external requests and requires no account. index.html is byte-identical. JavaScript must be enabled locally. Run full lab produces eight actual DOM snapshots of three call links. Expand each snapshot for displayed text, accessible label, raw href, comparable number and result. Save last result JSON exports those records. The fixture container is inert: rendered links remain readable by the DOM checker but ordinary keyboard, pointer and auxiliary interaction is disabled. Browsers without native inert support do not mount the fixture; the lab is disabled and the observation checker remains available. This is a controlled fixture behavior, not a guarantee about arbitrary scripted activation or modified pages. Never dial example numbers. All fixture numbers and results are synthetic. This is original Lonta replacement code, NOT CallRail or any other provider's script. The returning visitor state is an in-memory model. It is not a cookie, browser-restoration or attribution test. Blocked script means the lab leaves its replacement function uncalled; it does not emulate a provider's network behavior. CHECK YOUR OWN PAGE Only run console code you have reviewed on a page you control. Read console-snippet.js, optionally set window.tapAuditOptions, then paste the snippet in developer tools. It reads DOM candidates without network, clicks, mutations or persistence. It writes tapAuditResult to window and prints a table. Copy tapAuditResult.rows into the tool's JSON input. Example configuration (replace with your known setup): window.tapAuditOptions = { country: 'US', expected: '+12025550101', fallback: '+12025550100' }; Use country: 'global' to require +country-code input. US mode explicitly allows NANP 10 digits or leading 1. Number assignment, ownership and country code allocation are not validated. Syntax comparison is conservative; unsupported or ambiguous values stay unknown. Extensions, including zero, remain significant. Short codes, vanity numbers, phone-context, pauses, isub and multiple displayed numbers require manual inspection. Paste observations as a JSON array: [{"id":"mobile-bar","text":"(202) 555-0101", "href":"tel:+12025550100","accessible":"Call (202) 555-0101"}] Only the four fields above are needed; a missing field may be omitted. The offline tool never parses pasted HTML. Input is rendered with textContent. Maximum input: 200 rows / 100,000 characters. Clear inputs resets observations. Load defective sample restores the synthetic example. Nothing is saved automatically. JSON export contains the observations you supply. Do not include customer or confidential account data in a report that you intend to share. RESULTS PASS: comparable displayed number and destination agree; any parseable number in the accessible label also agrees. An explicit numeric accessible label that cannot be parsed is UNKNOWN. Generic nonnumeric accessible labels receive NOT_NUMBERED for their label comparison; they do not prevent a visible-number/link consistency PASS. Expected number, if supplied, also matches. An empty expectation cannot confirm the intended tracking number. Attribution and call routing remain UNVERIFIED in every result. FAIL: observed disagreement, wrong expected destination or missing/non-tel link on a detected phone CTA. UNKNOWN: insufficient or unsupported input, invalid expected/fallback number, or no observed CTA. FALLBACK: displayed number and destination match your declared fallback. It does not confirm the expected tracking number or that the line works. SCANNING LIMITS The DOM snapshot scans visible light-DOM tel anchors, number-labeled anchors (including anchors missing href), and data-phone-cta elements. It includes off-screen but rendered elements so scroll to inspect them. It excludes display:none, visibility:hidden and opacity:0 on the element. Clipped text, ancestor opacity, overlays, generated text, complete accessible-name computation, frames, shadow roots, image-only numbers, buttons without data-phone-cta and custom JavaScript calling are outside its coverage. Candidate count zero is UNKNOWN, never PASS. Multiple offices should be audited in separate scopes with their own expectations. The console snippet installs no observer. Rerun after asynchronous changes, navigation, Back, revisits and controlled script blocking. FILES / REPRODUCTION - audit.js: shared comparison logic and actual DOM reader (MIT). - fixture.js: controlled deliberate text-only defect and repair (MIT). - app.js: offline UI and eight-state journey (MIT). - tool.template.html: HTML and styles used to generate the tool. - build.mjs: embeds those three scripts into identical HTML files and generates the self-contained console snippet. Run: node build.mjs - audit.test.mjs: dependency-free behavior tests. Run: node --test audit.test.mjs - browser.test.mjs: actual Chromium DOM/file:// tests, 390px viewport, input safety, export, reset and zero HTTP requests. Requires existing Node + Playwright + its Chromium browser, outside the offline tool. Place the extracted directory under a project already providing node_modules/playwright, then run: node browser.test.mjs No dependency is required merely to open the HTML tool. - fixture-safety.test.mjs: focus, tab navigation, pointer hit testing, ordinary/auxiliary/context event targets and 8-state audits in the installed Chromium, Firefox and WebKit engines. The test itself cancels phone-target events defensively; no protocol handler is launched. Run with existing Playwright browsers: node fixture-safety.test.mjs - lab-results.json: generated by the browser test from the tool's actual JSON download; 8 states / 24 per-CTA snapshots, no customer data. - package.json: marks audit.js as CommonJS for the standalone Node tests. - make-bundle.py: deterministic zip builder using Python standard library. After rebuilding/testing run: python3 make-bundle.py - LICENSE.txt: license for all original code in this directory. The bundle contains exact copies of the distributed tool, source, fixture, tests, this README, license and generated example results. It excludes itself. No third-party library is redistributed in the tool or bundle. BACKGROUND SOURCES, READ 2026-10-24 CallRail installation: https://support.callrail.com/hc/en-us/articles/5711709638541 CallRail DNI overview: https://support.callrail.com/hc/en-us/articles/5711814948877 CallRail manual testing: https://support.callrail.com/hc/en-us/articles/5711376255501 CallRail Swap.js documentation (relevant complete section): https://apidocs.callrail.com/#swap-js MDN telephone anchors: https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/a#linking_to_telephone_numbers MDN history navigation: https://developer.mozilla.org/en-US/docs/Web/API/History_API/Working_with_the_History_API No vendor source code is included or executed. Sources explain the mechanisms; generated results only describe this original synthetic lab. MDN inert attribute / DOM property (read 2026-10-24): https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/inert https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/inert