PageSourceSearch

https://pblfg.com/

html pblfg.com collected 2026-10-02 01:38:48 UTC 25,109 bytes, 539 lines download raw bytes

1<!doctype html>
2<html lang="en">
3  <head>
4    <meta charset="UTF-8" />
5    <!-- Google tag (gtag.js) -->
vendor: 68 bytes, lines 5-6
5
6    <script async src="https://www.googletagmanager.com/gtag/js?id=
6G-5XRNJJF51K
vendor: 16 bytes, lines 6-7
6"></script>
7    
7<script>
8      window.dataLayer = window.dataLayer || [];
9      function gtag(){dataLayer.push(arguments);}
10      gtag('js', new Date());
11      var isNativeApp = typeof window.Capacitor !== 'undefined' || navigator.userAgent.indexOf('CapacitorApp') > -1 || window.location.protocol === 'capacitor:';
12      gtag('config', 'G-5XRNJJF51K', {
13        'app_platform': isNativeApp ? 'ios_native' : 'web',
14        'custom_map': { 'dimension1': 'app_platform' }
15      });
16    </script>
16
17    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, user-scalable=no, maximum-scale=1.0" />
18    
19    <style>
20      /* Minimal fallback - theme gradient applied by inline script below */
21      /* CRITICAL: Dark background prevents white flash on iOS during any reload */
22      /* Also covers Dynamic Island / safe area with solid color */
23      html, body {
24        margin: 0;
25        padding: 0;
26        min-height: 100vh;
27        min-height: 100dvh;
28        background: #000;
29        background-color: #000;
30      }
31      /* Ensure the safe-area behind Dynamic Island is always dark */
32      html {
33        background-color: var(--loader-bg, #000) !important;
34      }
35    </style>
36    
37    <title>MATCHDAY by Pickleball Inc. - Get Scores. Make Predictions.</title>
38    <meta name="description" content="Track Live Scores. Get Player Alerts. Make Predictions.">
39    <meta name="author" content="PBScores" />
40    
41    <!-- PWA and Mobile App Meta Tags -->
42    <!-- Will be updated dynamically by themeColorManager.ts based on selected theme -->
43    <meta name="theme-color" content="#000000" />
44    <meta name="apple-mobile-web-app-capable" content="yes" />
45    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
46    <meta name="apple-mobile-web-app-title" content="MATCHDAY by Pickleball Inc." />
47    <link rel="apple-touch-icon" href="/pblfg-2026-logo-6.webp">
48
49    <!-- Preload the app logo: it is the LCP candidate on the initial route
50         (header brand + loading splash) so kicking it off in <head> shaves
51         300-800ms off first paint on slow connections. -->
52    <link rel="preload" as="image" href="/pblfg-2026-logo-6.webp" fetchpriority="high" />
53
54    <!-- Browser compatibility check -->
55    
55<script>
56      (function() {
57        // Check for critical features
58        var hasRequiredFeatures = 
59          typeof Promise !== 'undefined' && 
60          typeof fetch !== 'undefined' && 
61          typeof localStorage !== 'undefined' &&
62          typeof Object.assign !== 'undefined';
63        
64        if (!hasRequiredFeatures) {
65          document.addEventListener('DOMContentLoaded', function() {
66            document.body.innerHTML = '<div style="padding: 20px; font-family: sans-serif; max-width: 600px; margin: 0 auto;"><h1>Browser Not Supported</h1><p>Your browser is missing features required to run this app. Please update to a modern browser like Chrome, Safari, Firefox, or Edge.</p></div>';
67          });
68        }
69      })();
70    </script>
70
71
72  <!-- Open Graph / Facebook -->
73  <meta property="og:type" content="website" />
74  <meta property="og:url" content="https://pblfg.com/" />
75  
76  
77  <meta property="og:image" content="https://storage.googleapis.com/gpt-engineer-file-uploads/WJrVyGkoLCPJdlPU9ic4HC8kja82/social-images/social-1774734549287-sharecard.webp">
78  <meta property="og:image:secure_url" content="https://pblfg.com/sharecard.png" />
79  <meta property="og:image:width" content="1200" />
80  <meta property="og:image:height" content="630" />
81  <meta property="og:image:alt" content="MATCHDAY - Real-Time Pickleball Scores" />
82
83  <!-- Twitter -->
84  <meta name="twitter:card" content="summary_large_image" />
85  <meta name="twitter:url" content="https://pblfg.com/" />
86  <meta name="twitter:domain" content="pblfg.com" />
87  <meta name="twitter:image" content="https://storage.googleapis.com/gpt-engineer-file-uploads/WJrVyGkoLCPJdlPU9ic4HC8kja82/social-images/social-1774734549287-sharecard.webp">
88  <meta name="twitter:image:alt" content="MATCHDAY - Real-Time Pickleball Scores" />
89    
90  
91  <!-- Preload remote-hosted fonts (Lovable Cloud) — kept out of the iOS bundle to avoid Apple ITMS-90853 -->
92  <link rel="preconnect" href="https://grwhdhnlafqrcmiuqhhi.supabase.co" crossorigin>
93  <link rel="preconnect" href="https://cdn.fontshare.com" crossorigin>
94  <link rel="preload" href="https://cdn.fontshare.com/wf/D2VP4PR6KFISH7CFEZQBVDPHE6XGGZWX/KE6JJBLOTZ2VLNFBKAZFXUVCHRYC6XSF/JFA5HRDFNHFTHIDA47YRUKD32JZ4ME6V.woff2" as="font" type="font/woff2" crossorigin>
95  <link rel="preload" href="https://cdn.fontshare.com/wf/ATKS7EHYU4PKFTXRA4UFAHPY7XS75QMY/OYTCFLQCR7FVKK7FIO7TCJPY4YG22I3S/GKSURDSYOFIC3Y6F5SMWSENDSAB2YMKC.woff2" as="font" type="font/woff2" crossorigin>
96  <link rel="preload" href="https://grwhdhnlafqrcmiuqhhi.supabase.co/storage/v1/object/public/app-fonts/PressStart2P-Regular.woff2" as="font" type="font/woff2" crossorigin>
97  
98  <!-- Handwritten fonts for Pick 'Em -->
99  <link rel="preconnect" href="https://fonts.googleapis.com">
100  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
101  <link href="https://fonts.googleapis.com/css2?family=Fredericka+the+Great&family=Kalam:wght@700&family=Permanent+Marker&family=Rock+Salt&display=swap" rel="stylesheet">
102  
103  <!-- Favicon is set on line 26 -->
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  <link rel="icon" type="image/webp" href="/pblfg-2026-logo-6.webp">
165  <link rel="preload" as="image" href="/pblfg-2026-logo-6.webp" fetchpriority="high">
166  
167  
168  
169  
170  <meta property="og:title" content="MATCHDAY by Pickleball Inc. - Get Scores. Make Predictions.">
171  <meta name="twitter:title" content="MATCHDAY by Pickleball Inc. - Get Scores. Make Predictions.">
172  <meta property="og:description" content="Track Live Scores. Get Player Alerts. Make Predictions.">
173  <meta name="twitter:description" content="Track Live Scores. Get Player Alerts. Make Predictions.">
174  
174<script type="module" crossorigin src="/assets/index-BgCZMvjj.js"></script>
174
175  <link rel="modulepreload" crossorigin href="/assets/capacitor-DSpR9wll.js">
176  <link rel="modulepreload" crossorigin href="/assets/react-vendor-Q2BSRknM.js">
177  <link rel="modulepreload" crossorigin href="/assets/supabase-DoZmW4Yf.js">
178  <link rel="modulepreload" crossorigin href="/assets/ui-radix-DzQ_orwq.js">
179  <link rel="modulepreload" crossorigin href="/assets/lucide-Ckh7y__x.js">
180  <link rel="modulepreload" crossorigin href="/assets/query-BLOP9k_M.js">
181  <link rel="modulepreload" crossorigin href="/assets/date-utils-DaNoSKVa.js">
182  <link rel="stylesheet" crossorigin href="/assets/index-C5lWRha4.css">
183<link rel="manifest" href="/manifest.webmanifest">
183<script defer src="/~flock.js" data-proxy-url="/~api/analytics"></script>
183</head>
184
185  <body>
186    
186<script>
187      // Apply theme gradient IMMEDIATELY before any content renders
188      (function() {
189        // Default to midnight-blue so native/web startup stays dark before app state loads
190        const theme = localStorage.getItem('theme') || 'midnight-blue';
191        
192        // Theme loader backgrounds - must match themeColorManager.ts
193        const themeGradients = {
194          'midnight-blue': 'hsl(220 50% 4%)',
195          'pickleball-dark': 'hsl(135 50% 1%)',
196          'pro-midnight': 'hsl(260 50% 6%)',
197          'xmas': 'hsl(350 40% 6%)',
198          'pure-void': 'hsl(210 20% 5%)',
199          'crimson-abyss': 'hsl(0 42% 4%)',
200          'burnt-sienna': 'hsl(18 45% 3%)',
201          'purple-haze': 'hsl(260 50% 6%)',
202          'electric-teal': 'hsl(185 55% 1%)',
203          'neon-rose': 'hsl(335 55% 4%)',
204          'ocean-breeze': 'hsl(195 100% 98%)',
205          'original-refined': 'hsl(0 0% 100%)',
206          'championship-gold': 'hsl(0 0% 100%)',
207          'pearl-mist': 'hsl(0 0% 100%)',
208          'sunset-rally': 'hsl(30 30% 97%)',
209          'carbon-fiber': 'hsl(0 0% 12%)'
210        };
211
212        // Fallback to midnight-blue if theme not found
213        const bgGradient = themeGradients[theme] || themeGradients['midnight-blue'];
214
215        // Set data-theme attribute for CSS variables
216        document.documentElement.setAttribute('data-theme', theme);
217
218        // Single source-of-truth for ALL pre-content loader phases
219        document.documentElement.style.setProperty('--loader-bg', bgGradient);
220        window.__loaderBg = bgGradient;
221
222        // Apply background to both html and body for full coverage
223        document.documentElement.style.background = 'var(--loader-bg)';
224        document.body.style.background = 'var(--loader-bg)';
225        document.body.style.margin = '0';
226        document.body.style.padding = '0';
227
228        // Root stays transparent (React paints its own backgrounds)
229        const initialLoader = document.getElementById('root');
230        if (initialLoader) {
231          initialLoader.style.background = 'transparent';
232        }
233      })();
234      
235      // Apply logo based on saved app icon preference
236      (function() {
237        const appIcon = localStorage.getItem('app_icon') || 'default';
238        const logoMap = {
239          'default': '/pblfg-2026-logo-6.webp',
240          'retro': '/retro-logo.png',
241          'winter': '/winter-logo.png',
242          'holiday': '/winter-logo.png' // Legacy alias
243        };
244        window.__appLogoSrc = logoMap[appIcon] || '/pblfg-2026-logo-6.webp';
245      })();
246    </script>
246
247    <!-- Portal container for fixed elements - TRUE SIBLING to #root -->
248    <div id="fixed-portal" style="position: fixed !important; bottom: 0 !important; left: 0 !important; right: 0 !important; z-index: 9999 !important; transform: none !important; will-change: auto !important; contain: layout style !important; isolation: isolate !important; pointer-events: none;"></div>
249
250    <!-- Static loading screen shown before React loads (keep OUTSIDE #root so React doesn't wipe it) -->
251    <div id="initial-loader">
252      <img id="loader-logo" src="/pblfg-2026-logo-6.webp" alt="MATCHDAY" onerror="this.onerror=null; this.src='/pblfg-2026-logo-6.webp';" />
253      <!-- Status text removed - logo pulse is sufficient -->
254      <!-- Recovery UI - hidden initially, shown on timeout -->
255      <div id="loader-recovery" style="display: none; flex-direction: column; align-items: center; gap: 12px; margin-top: 24px; padding: 0 24px;">
256        <p style="color: rgba(255,255,255,0.65); font-size: 14px; font-family: sans-serif; margin: 0 0 4px 0; text-align: center;">Taking longer than expected.<br/>Tap Retry, or Reset if Retry doesn't help.</p>
257        <button id="loader-retry-btn" style="padding: 12px 24px; background: rgba(59,130,246,0.85); color: white; border: none; border-radius: 8px; font-size: 16px; font-weight: 600; min-width: 200px; cursor: pointer;">Retry</button>
258        <button id="loader-reset-btn" style="padding: 10px 24px; background: transparent; color: rgba(255,255,255,0.7); border: 1px solid rgba(255,255,255,0.25); border-radius: 8px; font-size: 14px; font-weight: 500; min-width: 200px; cursor: pointer;">Reset App Data</button>
259      </div>
260      
260<script>
261        document.getElementById('loader-retry-btn')?.addEventListener('click', async function() {
262          this.textContent = 'Retrying...';
263          this.disabled = true;
264          try { window.__pblfgBootBeacon && window.__pblfgBootBeacon('User tapped Retry', {}); } catch(e) {}
265          try {
266            if ('serviceWorker' in navigator) {
267              var regs = await navigator.serviceWorker.getRegistrations();
268              await Promise.all(regs.map(function(r) { return r.unregister(); }));
269            }
270            if ('caches' in window) {
271              var names = await caches.keys();
272              await Promise.all(names.map(function(n) { return caches.delete(n); }));
273            }
274            sessionStorage.clear();
275          } catch(e) { console.error('Recovery cleanup failed:', e); }
276          window.location.reload();
277        });
278        document.getElementById('loader-reset-btn')?.addEventListener('click', async function() {
279          this.textContent = 'Resetting...';
280          this.disabled = true;
281          try { window.__pblfgBootBeacon && window.__pblfgBootBeacon('User tapped Reset App Data', {}); } catch(e) {}
282          // Preserve essentials so users aren't logged out by a recovery wipe.
283          // Mirrors storageHealthManager.nuclearCleanup(): theme + auth session +
284          // preserve-auth flag. Auth key matches AUTH_STORAGE_KEY in
285          // src/utils/sessionPersistence.ts — keep these two in sync.
286          var theme = null, authToken = null, preserveAuthFlag = null;
287          try { theme = localStorage.getItem('theme'); } catch(e) {}
288          try { authToken = localStorage.getItem('sb-grwhdhnlafqrcmiuqhhi-auth-token'); } catch(e) {}
289          try { preserveAuthFlag = localStorage.getItem('pbpulse_preserve_auth_on_cleanup'); } catch(e) {}
290          // Honor the kill switch: if an admin disabled preservation, drop the token.
291          if (preserveAuthFlag === 'false') { authToken = null; }
292          try { localStorage.clear(); } catch(e) {}
293          try { sessionStorage.clear(); } catch(e) {}
294          if (theme) { try { localStorage.setItem('theme', theme); } catch(e) {} }
295          if (authToken) { try { localStorage.setItem('sb-grwhdhnlafqrcmiuqhhi-auth-token', authToken); } catch(e) {} }
296          if (preserveAuthFlag !== null) { try { localStorage.setItem('pbpulse_preserve_auth_on_cleanup', preserveAuthFlag); } catch(e) {} }
297          try {
298            if ('serviceWorker' in navigator) {
299              var regs = await navigator.serviceWorker.getRegistrations();
300              await Promise.all(regs.map(function(r) { return r.unregister(); }));
301            }
302            if ('caches' in window) {
303              var names = await caches.keys();
304              await Promise.all(names.map(function(n) { return caches.delete(n); }));
305            }
306            // IndexedDB wipe — the layer ordinary "clear cache" misses and a top
307            // suspect for the WebView "must reinstall" failure mode.
308            if (window.indexedDB && indexedDB.databases) {
309              try {
310                var dbs = await indexedDB.databases();
311                await Promise.all((dbs || []).map(function(d) {
312                  return new Promise(function(res){
313                    try { var r = indexedDB.deleteDatabase(d.name); r.onsuccess = r.onerror = r.onblocked = function(){ res(); }; }
314                    catch(e) { res(); }
315                  });
316                }));
317              } catch(e) {}
318            }
319          } catch(e) { console.error('Reset failed:', e); }
320          window.location.reload();
321        });
322      </script>
322
323      
323<script>
324        // Only swap the loader logo when a custom app icon is selected, and
325        // decode it off-screen first. Assigning a new (uncached) src directly
326        // blanks the image for a frame or two — that is the "flash of
327        // emptiness, then the logo pops back" on cold start.
328        (function () {
329          var el = document.getElementById('loader-logo');
330          var want = window.__appLogoSrc || '/pblfg-2026-logo-6.webp';
331          if (!el || !want || want === '/pblfg-2026-logo-6.webp') return;
332          var pre = new Image();
333          pre.onload = function () { el.src = want; };
334          pre.src = want;
335        })();
336
337        // Track UI readiness at the HTML level so the native splash overlay can
338        // be lifted at the right moment (see setupReactMountListener in
339        // CustomBridgeViewController.swift) even if it asks late.
340        window.addEventListener('pblfg-ui-ready', function () {
341          window.__PBLFG_UI_READY__ = true;
342        });
343      </script>
343
344
345    </div>
346
347    <div id="root"></div>
348
349    <style>
350      #root {
351        background: transparent;
352      }
353
354      #initial-loader {
355        position: fixed;
356        inset: 0;
357        display: flex;
358        flex-direction: column;
359        align-items: center;
360        justify-content: center;
361        gap: 1rem;
362        z-index: 9999;
363        background: var(--loader-bg, #000);
364      }
365
366      #loader-logo {
367        width: 100px;
368        height: 100px;
369        position: relative;
370        z-index: 9999;
371      }
372
373      /* When refreshing, hide the big logo - React will show bouncing pickleball */
374      #initial-loader.is-refreshing #loader-logo {
375        display: none;
376      }
377
378      /* Already-booted-this-session: skip the splash entirely so in-session
379         reloads and same-tab navigations don't gate content behind the splash. */
380      html.pblfg-booted #initial-loader {
381        display: none !important;
382      }
383
384      @keyframes pulse {
385        0%, 100% {
386          opacity: 1;
387        }
388        50% {
389          opacity: 0.5;
390        }
391      }
392    </style>
393
394    
394<script>
395      // Already booted this session? Skip the splash entirely — the React app
396      // will paint its own skeletons. Restores fast in-session navigation so
397      // only true cold boot pays the splash-gating cost.
398      try {
399        if (sessionStorage.getItem('pblfg_booted') === '1') {
400          document.documentElement.classList.add('pblfg-booted');
401        }
402      } catch (e) { /* ignore */ }
403
404      // Check if this is a refresh (not first load) - hide the logo loader
405      if (sessionStorage.getItem('pblfg_refreshing') === 'true') {
406        document.getElementById('initial-loader')?.classList.add('is-refreshing');
407      }
408
409      // ─────────────────────────────────────────────────────────────────────
410      // HTML-level boot watchdog
411      //
412      // Runs OUTSIDE the React/JS bundle so it works even if the bundle never
413      // loads (the actual "must reinstall" failure mode). Steps:
414      //   • If React never mounts, beacon the failure and keep the clean loader.
415      //     Do NOT show a Retry panel automatically: iOS can snapshot that panel
416      //     while backgrounded and then flash it on the next cold start even when
417      //     the app is about to load normally.
418      // ─────────────────────────────────────────────────────────────────────
419      (function setupBootWatchdog() {
420        var startedAt = Date.now();
421        var WATCHDOG_MS = 15000;
422        // Track whether the page was ever hidden (backgrounded) during the boot
423        // window. iOS suspends the WebView's JS runloop when the app is
424        // backgrounded; if our setTimeout was queued before suspension and
425        // fires hours later on resume, it produces a false "React never
426        // mounted" beacon. We use this flag — plus an elapsed-time sanity
427        // check — to suppress those false positives.
428        var wasHiddenDuringBoot = (typeof document !== 'undefined' && document.visibilityState === 'hidden');
429        try {
430          document.addEventListener('visibilitychange', function () {
431            if (document.visibilityState === 'hidden') wasHiddenDuringBoot = true;
432          }, { passive: true });
433        } catch (e) { /* no-op */ }
434
435        function reactMounted() {
436          var root = document.getElementById('root');
437          return !!(root && root.children && root.children.length > 0);
438        }
439
440        // If React mounts after the recovery UI was already shown, hide it
441        // immediately so users never see a flash of "Retry" on a slow cold boot.
442        try {
443          window.addEventListener('pblfg-react-mounted', function () {
444            var recovery = document.getElementById('loader-recovery');
445            if (recovery) recovery.style.display = 'none';
446          }, { once: true });
447        } catch (e) { /* no-op */ }
448
449        // iOS WKWebView snapshot defense: iOS captures whatever is on screen
450        // when the app is backgrounded and replays it as the launch image on
451        // the next cold start. If the Retry UI was ever visible at suspend
452        // time, every future launch will flash that snapshot for a split
453        // second before React paints. Force the recovery UI hidden on every
454        // background/foreground transition so the snapshot is always clean.
455        try {
456          var hideRecovery = function () {
457            var recovery = document.getElementById('loader-recovery');
458            if (recovery) recovery.style.display = 'none';
459          };
460          document.addEventListener('visibilitychange', function () {
461            if (document.visibilityState === 'hidden') hideRecovery();
462          }, { passive: true });
463          window.addEventListener('pagehide', hideRecovery, { passive: true });
464          window.addEventListener('pageshow', hideRecovery, { passive: true });
465        } catch (e) { /* no-op */ }
466
467        function beacon(message, extra) {
468          try {
469            var apiKey = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Imdyd2hkaG5sYWZxcmNtaXVxaGhpIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjI2NDk4NjMsImV4cCI6MjA3ODIyNTg2M30.AS7_JF_qguIDtEEtN6YhNrACYmEzw_UdufeXVK1vXjg';
470            var ua = navigator.userAgent || '';
471            var platform = /Android/i.test(ua) ? 'android' : (/iPhone|iPad|iPod/i.test(ua) ? 'ios' : 'web');
472            fetch('https://grwhdhnlafqrcmiuqhhi.supabase.co/rest/v1/error_analytics', {
473              method: 'POST',
474              headers: {
475                'Content-Type': 'application/json',
476                'apikey': apiKey,
477                'Authorization': 'Bearer ' + apiKey,
478                'Prefer': 'return=minimal'
479              },
480              body: JSON.stringify({
481                error_message: ('[BOOT-WATCHDOG:' + platform + '] ' + message).substring(0, 2000),
482                error_stack: JSON.stringify(extra || {}).substring(0, 4000),
483                context: 'html-boot-watchdog',
484                page_path: '/',
485                is_native_app: /wv\)/.test(ua) || /Capacitor/i.test(ua),
486                user_agent: ua.substring(0, 500)
487              })
488            }).catch(function(){});
489          } catch (e) { /* never throw from a crash reporter */ }
490        }
491        // Expose for main.tsx to reuse (avoids duplicate beacon code).
492        window.__pblfgBootBeacon = beacon;
493
494        setTimeout(function () {
495          if (reactMounted() || window.__REACT_MOUNTED__) return;
496
497          var elapsed = Date.now() - startedAt;
498
499          // Suppress false positives from iOS WebView suspension: if the page
500          // was hidden during the boot window OR the timer fired noticeably
501          // late (runloop was paused), this isn't a real "React never mounted"
502          // failure — the JS thread was simply suspended and just resumed.
503          if (wasHiddenDuringBoot || document.visibilityState === 'hidden' || elapsed > WATCHDOG_MS + 4000) {
504            return;
505          }
506
507          // Final mount re-check after a short grace window — React often
508          // hydrates within a few hundred ms of the watchdog firing on slow
509          // cold boots, and showing the Retry UI for that brief sliver is the
510          // "flash of retry screen" users see.
511          setTimeout(function () {
512            if (reactMounted() || window.__REACT_MOUNTED__) return;
513
514            // Snapshot what we can about why React never mounted.
515            var snapshot = {
516              elapsed: Date.now() - startedAt,
517              hasFixedPortal: !!document.getElementById('fixed-portal'),
518              hasInitialLoader: !!document.getElementById('initial-loader'),
519              mainScriptPresent: !!document.querySelector('script[src*="main.tsx"], script[src*="assets/index"]'),
520              sessionRefreshing: (function(){ try { return sessionStorage.getItem('pblfg_refreshing'); } catch(e){ return 'na'; } })(),
521              failureCount: (function(){ try { return localStorage.getItem('pbpulse_boot_failure_count') || '0'; } catch(e){ return 'na'; } })(),
522              firstInstall: (function(){ try { return localStorage.getItem('pbpulse_first_install_completed') !== '1' ? 'yes' : 'no'; } catch(e){ return 'na'; } })(),
523              online: navigator.onLine,
524              userAgent: (navigator.userAgent || '').substring(0, 200)
525            };
526            beacon('React never mounted within ' + WATCHDOG_MS + 'ms', snapshot);
527
528            // Keep the splash/loader clean. A visible Retry UI here is the source
529            // of the cold-start flash; actual native/web watchdogs can still
530            // reload or recover without presenting a stale snapshot to the user.
531            var recovery = document.getElementById('loader-recovery');
532            if (recovery) recovery.style.display = 'none';
533          }, 2500);
534        }, WATCHDOG_MS);
535      })();
536    </script>
536
537
538  </body>
539</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.