PageSourceSearch

https://homecasa.ai/

html homecasa.ai collected 2026-10-05 14:35:52 UTC 11,888 bytes, 215 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.0, maximum-scale=1, user-scalable=no, viewport-fit=cover" />
6    
6<script>
7      // Mobile landscape → iPad layout.
8      // Small phones in landscape (e.g. iPhone SE 667×375) have physical
9      // width < 768, so Tailwind's `md:` breakpoint never engages and they
10      // get the cramped mobile layout. Force the viewport to 820px wide in
11      // that case so the browser renders the iPad/tablet layout instead.
12      // We touch the viewport meta directly so this works before React mounts.
13      (function() {
14        var meta = document.querySelector('meta[name="viewport"]');
15        if (!meta) return;
16        var PORTRAIT = 'width=device-width, initial-scale=1.0, maximum-scale=1, user-scalable=no, viewport-fit=cover';
17        var LANDSCAPE_TABLET = 'width=820, initial-scale=1.0, maximum-scale=1, user-scalable=no, viewport-fit=cover';
18        function apply() {
19          // Use screen.width/height which reflect physical device dimensions,
20          // not the (possibly already-zoomed) viewport innerWidth.
21          var sw = window.screen && window.screen.width || window.innerWidth;
22          var sh = window.screen && window.screen.height || window.innerHeight;
23          var landscape = window.matchMedia('(orientation: landscape)').matches;
24          // Smallest dimension is the true physical width on phones.
25          var minDim = Math.min(sw, sh);
26          var isPhoneSizedLandscape = landscape && minDim < 768;
27          var desired = isPhoneSizedLandscape ? LANDSCAPE_TABLET : PORTRAIT;
28          if (meta.getAttribute('content') !== desired) {
29            meta.setAttribute('content', desired);
30          }
31        }
32        apply();
33        window.addEventListener('orientationchange', function() { setTimeout(apply, 50); });
34        window.addEventListener('resize', apply);
35      })();
36    </script>
36
37    <meta name="theme-color" content="#120E0A" />
38    <meta name="apple-mobile-web-app-capable" content="yes" />
39    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
40    <meta name="apple-mobile-web-app-title" content="HomeCasa" />
41    <meta name="description" content="HomeCasa™ — The Intelligence Layer for Homes. Available exclusively through Certified Design Partners." />
42    <meta property="og:title" content="HomeCasa™ — The Intelligence Layer for Homes" />
43    <meta property="og:description" content="The Intelligence Layer for Homes. Designed. Integrated. Orchestrated. Available exclusively through Certified Design Partners." />
44    <meta property="og:type" content="website" />
45    <meta property="og:url" content="https://mycasa.replit.app/" />
46    <meta property="og:image" content="https://mycasa.replit.app/og-image.png?v=7" />
47    <meta property="og:image:width" content="1200" />
48    <meta property="og:image:height" content="630" />
49    <meta name="twitter:card" content="summary_large_image" />
50    <meta name="twitter:title" content="HomeCasa™ — The Intelligence Layer for Homes" />
51    <meta name="twitter:description" content="The Intelligence Layer for Homes. Available exclusively through Certified Design Partners." />
52    <meta name="twitter:image" content="https://mycasa.replit.app/og-image.png?v=7" />
53    <link rel="icon" type="image/png" href="/favicon.png?v=4" />
54    <link rel="icon" type="image/png" sizes="192x192" href="/icon-192.png?v=4" />
55    <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png?v=4" />
56    <link rel="manifest" href="/manifest.json?v=4" />
57    <link rel="preconnect" href="https://fonts.googleapis.com">
58    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
59    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
60    <title>HomeCasa™ — The Intelligence Layer for Homes</title>
61    
61<script type="module" crossorigin src="/assets/index-CShcmsL3.js"></script>
61
62    <link rel="stylesheet" crossorigin href="/assets/index-kla4FAcD.css">
63  </head>
64  <body>
65    <div id="root">
66      <div id="loading-indicator" style="display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;font-family:system-ui,sans-serif;background:#120E0A;">
67        <div style="width:40px;height:40px;border:3px solid rgba(201,165,90,0.15);border-top-color:rgba(201,165,90,0.7);border-radius:50%;animation:spin 1s linear infinite;"></div>
68        <p style="margin-top:16px;color:rgba(201,165,90,0.5);font-size:13px;letter-spacing:0.1em;">Loading HomeCasa...</p>
69      </div>
70      <style>@keyframes spin{to{transform:rotate(360deg)}}</style>
71    </div>
72    
72<script>
73      // Global error handler for older browsers
74      window.onerror = function(msg, url, line, col, error) {
75        var root = document.getElementById('root');
76        if (root) {
77          root.innerHTML = '<div style="padding:20px;text-align:center;font-family:system-ui;max-width:400px;margin:0 auto;background:#120E0A;min-height:100vh;display:flex;flex-direction:column;align-items:center;justify-content:center;"><h2 style="color:rgba(201,165,90,0.9);font-size:20px;">Something went wrong</h2><p style="color:rgba(245,235,220,0.5);word-break:break-all;font-size:14px;margin:16px 0;">' + msg + '</p><button onclick="location.reload()" style="padding:12px 24px;background:rgba(201,165,90,0.15);color:rgba(201,165,90,0.9);border:1px solid rgba(201,165,90,0.3);border-radius:8px;font-size:16px;">Reload App</button><p style="margin-top:16px;"><a href="/compatibility" style="color:rgba(201,165,90,0.6);font-size:14px;">Check Device Compatibility</a></p></div>';
78        }
79        return false;
80      };
81    </script>
81
82    
82<script>
83      (function() {
84        if (!('serviceWorker' in navigator)) return;
85        var isProd = location.hostname === 'mycasa.replit.app' || location.hostname === 'homecasa.ai' || location.hostname === 'www.homecasa.ai';
86        if (!isProd) {
87          navigator.serviceWorker.getRegistrations().then(function(regs) {
88            regs.forEach(function(r) { r.unregister(); });
89          });
90          caches.keys().then(function(names) {
91            names.forEach(function(name) { caches.delete(name); });
92          });
93          return;
94        }
95        var reloading = false;
96        window.addEventListener('load', function() {
97          navigator.serviceWorker.register('/sw.js', { updateViaCache: 'none' })
98            .then(function(registration) {
99              console.log('SW registered:', registration);
100              registration.update();
101              if (registration.waiting) {
102                registration.waiting.postMessage('SKIP_WAITING');
103              }
104              registration.addEventListener('updatefound', function() {
105                var newWorker = registration.installing;
106                if (newWorker) {
107                  newWorker.addEventListener('statechange', function() {
108                    if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
109                      newWorker.postMessage('SKIP_WAITING');
110                    }
111                  });
112                }
113              });
114
115              // Poll for updates every 5 minutes so long-lived sessions
116              // pick up new deploys without a manual refresh.
117              setInterval(function() {
118                registration.update().catch(function() {});
119              }, 5 * 60 * 1000);
120
121              // Also check when the tab becomes visible again (e.g. user
122              // returns from background) and when the network reconnects.
123              document.addEventListener('visibilitychange', function() {
124                if (document.visibilityState === 'visible') {
125                  registration.update().catch(function() {});
126                }
127              });
128              window.addEventListener('online', function() {
129                registration.update().catch(function() {});
130              });
131            })
132            .catch(function(error) {
133              console.log('SW registration failed:', error);
134            });
135        });
136        navigator.serviceWorker.addEventListener('controllerchange', function() {
137          if (!reloading) {
138            reloading = true;
139            window.location.reload();
140          }
141        });
142
143        // Auto-recover from stale-chunk failures ("Importing a module script
144        // failed", "Failed to fetch dynamically imported module", etc.).
145        // These happen when the service worker cached an old index.html that
146        // points at JS chunks that no longer exist on the server. We clear
147        // caches + unregister SW + reload, all silently. A sessionStorage
148        // guard prevents an infinite recovery loop.
149        function isChunkLoadError(msg) {
150          if (!msg) return false;
151          msg = String(msg);
152          return /Importing a module script failed/i.test(msg)
153            || /Failed to fetch dynamically imported module/i.test(msg)
154            || /error loading dynamically imported module/i.test(msg)
155            || /ChunkLoadError/i.test(msg)
156            || /Loading chunk \d+ failed/i.test(msg)
157            || /Loading CSS chunk/i.test(msg);
158        }
159        var RECOVERY_KEY = '__hc_chunk_recovery_at';
160        function attemptChunkRecovery(reason) {
161          try {
162            var last = parseInt(sessionStorage.getItem(RECOVERY_KEY) || '0', 10);
163            // Don't loop: if we recovered less than 60s ago, give up and let
164            // the real error surface so the user can see it.
165            if (Date.now() - last < 60000) {
166              console.warn('[ChunkRecovery] Skipping — recovered recently. Reason:', reason);
167              return;
168            }
169            sessionStorage.setItem(RECOVERY_KEY, String(Date.now()));
170          } catch (e) {}
171          console.warn('[ChunkRecovery] Stale chunk detected, clearing caches and reloading:', reason);
172          var done = function() {
173            try { window.location.reload(); } catch (e) {}
174          };
175          var tasks = [];
176          try {
177            if ('serviceWorker' in navigator) {
178              tasks.push(navigator.serviceWorker.getRegistrations().then(function(regs) {
179                return Promise.all(regs.map(function(r) { return r.unregister(); }));
180              }).catch(function() {}));
181            }
182            if (typeof caches !== 'undefined' && caches.keys) {
183              tasks.push(caches.keys().then(function(names) {
184                return Promise.all(names.map(function(n) { return caches.delete(n); }));
185              }).catch(function() {}));
186            }
187          } catch (e) {}
188          Promise.all(tasks).then(done, done);
189          // Hard timeout in case the above hangs
190          setTimeout(done, 2500);
191        }
192        window.addEventListener('error', function(ev) {
193          var msg = (ev && (ev.message || (ev.error && ev.error.message))) || '';
194          var src = ev && ev.target && (ev.target.src || ev.target.href);
195          // Module script load failures often surface as a script element
196          // error event with no message — detect by tag + src ending in .js
197          if (isChunkLoadError(msg)) {
198            attemptChunkRecovery(msg);
199            return;
200          }
201          if (ev && ev.target && ev.target.tagName === 'SCRIPT' && src && /\.js(\?|$)/.test(src)) {
202            attemptChunkRecovery('script load failed: ' + src);
203          }
204        }, true);
205        window.addEventListener('unhandledrejection', function(ev) {
206          var reason = ev && ev.reason;
207          var msg = reason && (reason.message || reason.toString && reason.toString());
208          if (isChunkLoadError(msg)) {
209            attemptChunkRecovery(msg);
210          }
211        });
212      })();
213    </script>
213
214  </body>
215</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.